2009-10-21 8 views
0

J'ai deux tables:Pagination avec l'association hasMany CakePHP

Concurrent et Votes Votes Contestant hasMany

J'ai essayé de faire un compte (Vote.id) comme un vote pour que je puisse le placer sur la recordset et juste les paginer mais je n'ai aucune idée où le placer. Je l'ai fait sur le tableau des champs, mais il m'a donné le nombre total des voix quel que soit le candidat auquel ils appartiennent.

Les votes sont reliés entre eux dans le recordset Contestant donc ce que je fait était mon point de vue, je l'ai fait un compte (candidat à $ [Vote]), mais cela ne peut pas être paginé et mon client veut pouvoir trier les participants par votes.

Est-il possible que je peux faire quelque chose comme ça sur moi ?:

tri ('votes', 'count (Vote)'); ?>

Ou dois-je créer une requête qui compte tous les votes où Contestant.id = Votes.contestant_id?

Controller Contestant:

function index() { 
      $page = 'Contestants'; 
      $this->set('page', $page); 
      $this->paginate = 
      array(
        'order' => 'id ASC', 
        'contain' => array(
          'Vote' => array(
            'fields' => array("Vote.contestant_id",'Vote.id') 
          ) 
        ) 
      $conditions ["Contestant.active"] = 1; 
      $this->set('contestants', $this->paginate('Contestant', 

conditions $)); }

Répondre

0

Depuis CakePHP ne supporte pas le groupe par le comportement maîtrisable J'ai essayé une approche différente. Créer le paginate var pour le modèle de vote au lieu (Tout cela se fait dans le Contestants Controller):

var $paginate = array(
    'Vote'=>array(
     'limit'=>5, 
     'fields' => array(
     'Contestant.*, count(Vote.contestant_id) as Contestant_votes, Vote.id' 
     ), 
     'group' => array(
     'Vote.contestant_id' 
     ), 
     'order' => array(
     'Contestant_votes Desc' 
     ) 
    ), 
    'Contestant'=>array(
     'limit'=>5, 
     'order' => array(
     'Contestant.id Desc' 
     ) 
    ) 
); 

Et maintenant, dans mon contrôleur, je fais ce qui suit:

function index() { 
    $page = 'Contestants'; 
    $this->set('page', $page); 
    $conditions ["Contestant.active"] = 1; 
    $this->set('contestants', $this->paginate($this->Contestant->Vote,$conditions)); 
} 

Maintenant, les participants sont commandés par leur total de votes, bien que je n'arrive toujours pas à comprendre comment placer les Contestant_votes en tant que variable paginator car dans le jeu d'enregistrements, c'est dans un tableau et non dans l'un des tableaux de modèles utilisés pour paginer.

Merci Matt Huggins votre approche est celle qui m'a conduit à cette solution.

0

Découvrez la réponse de deceze dans cette question: CakePHP mathematic-calculation field?

Essentiellement, vous voulez faire quelque chose comme ça, je devine:

'contain' => array(
    'Vote' => array(
     'fields' => array('SUM(Vote.id) AS Contestant__votes'), 
     'group' => array('Vote.contestant_id'), 
    ) 
) 
+0

bizarre quand j'essaie votre suggestion est la requête ce qu'il construit. :: Requête: SELECT SUM ('Vote'.'id') AS Contestant__votes,' Vote'.'group', 'Vote'.''contestant_id' FROM' votes' AS 'Vote' OERE' Vote'.'contestant_id 'IN (1, 2) –

+0

Et il montre cette erreur: Le modèle" Vote "n'est pas associé au modèle" Vote ". Est-ce un bug? Pourquoi un besoin d'associer un modèle à soi-même? –

+0

Ok, il semble que CakePHP ne supporte pas le groupe par le comportement maîtrisable donc je l'ai fait quelque chose comme ceci: 'conditions de => "1 = 1 GROUP BY Vote.contestant_id" et génère cette requête SQL: SELECT Somme ('Vote'.'id') AS Contestant__votes,' Vote'.''contestant_id' FROM 'votes' AS' Vote' O WH 1 = 1 GROUPE PAR 'Vote'.''contestant_id' AND' Vote'.''contestant_id' IN (1, 2) –

0

Addition: Voulez-vous aussi trier par votes (total des voix) ascendant ou descendant? Si oui, vous ne pouvez pas le faire facilement par la méthode de pagination par défaut de cakephp.

Pour cela, vous avez besoin d'un peu tweak. Voici les détails sur cette astuce: CakePHP Advanced Pagination – sort by derived field

espérons que vous trouveriez utile.

Merci Adnan

0

Pour la relation spécifique que vous définissez, vos besoins sont bien servis par counter-caching.

Vous devrez définir un nouveau champ dans votre tableau contestants: vote_count. Ensuite, dans votre modèle de vote, vous devez mettre à jour la définition $belongsTo légèrement:

class Votes extends AppModel 
{ 
    var $belongsTo = array(
     'Contestant' => array('counterCache' => true) 
    ); 
} 

Maintenant, à chaque fois qu'un dossier de vote est enregistré, le champ vote_count du candidat de parents seront mis à jour. Maintenant, vous pouvez simplement trier par Contestant.vote_count comme vous le feriez pour tout autre domaine Contestant:

class ContestantsController extends AppController 
{ 
    // Controller stuff that comes before... 

    function index() 
    { 
     $this->paginate = array('Contestant' => array(
      'conditions' => array('Contestant.active' => 1), 
      'order' => array('Contestant.vote_count' => 'DESC'), 
     )); 

     $contestants = $this->paginate('Contestants'); 

     $this->set(compact('contestants')); 
    } 

    // Controller stuff that comes after... 
} 
Questions connexes