2011-11-09 5 views
0

J'ai une hiérarchie de modèles CakePHP qui ressemble à:Rejoindre la table parent dans CakePHP Model-> find()

Users > Feedfolders > Feeds > Entries

À partir de l'FeedsController, je suis en train d'obtenir un compte de tous Entrées non lues basées sur l'ID utilisateur regroupées par ID de flux. Je ne sais vraiment pas comment je devrais le faire d'une manière qui correspond à la façon de faire de Cake. Je me sens comme la compréhension de Cake des modèles basés sur les propriétés $belongsTo et $hasMany dans les modèles devrait le laisser résoudre les jointures de manière appropriée, mais je ne suis pas sûr de ce que je fais mal. J'ai essayé plusieurs variantes find() sans succès. Plus récemment, j'ai essayé:

$result = $this->Feed->find('all', array(
    'conditions' => array('User.id' => $this->Auth->user('id'), 'Entry.read' => 1), 
    'fields' => array('count(Entry.feed_id) as Count', 'Entry.feed_id'), 
    'group' => 'Entry.feed_id', 
    'recursive' => 2) 
); 

qui génère l'instruction SQL suivante:

SELECT count(`Entry`.`feed_id`) as Count, `Entry`.`feed_id`, `Feed`.`id` 
FROM `feeds` AS `Feed` 
LEFT JOIN `feedfolders` AS `Feedfolder` ON (`Feed`.`feedfolder_id` = `Feedfolder`.`id`) 
WHERE `User`.`id` = 5 
AND `Entry`.`read` = 1 
GROUP BY `Entry`.`feed_id` 

qui se traduit par l'erreur suivante:

SQL Error: 1054: Unknown column 'Entry.feed_id' in 'field list' [CORE/cake/libs/model/datasources/dbo_source.php, line 684] 

Je vois le problème avec le SQL, et pourrait remettre écrire une requête pour faire ce que je veux, mais cela semble être le genre de chose qui devrait être faisable dans CakePHP sans avoir recours au SQL fait à la main.

Comment dois-je configurer mon appel find() pour faire ce que je veux, et, mon plan pour trouver des entrées non lues via le FeedsController est-il logique d'un point de vue MVC?

Répondre

1

Vous pouvez l'utiliser depuis le contrôleur pour le contrôleur.

/** 
* Bind the Feed model to the Entry model 
* and set a condition of 'read' => false 
*/ 
$this->Feed->bindModel(array(
    'hasMany' => array(
    'Entry' => array(
     'conditions' => array(
     'Entry.read' => false 
    ) 
    ) 
) 
)); 

/** 
* Get all the feeds and their accompanying 
* entries that belong to the current user 
*/ 
$unread = $this->Feed->find('all', array(
    'conditions' => array(
    'Feedfolder.user_id' => $this->Auth->user('id') 
) 
)); 

Que se passe-t-il ici?

Tout d'abord, nous lient le RSS modèle à l'aide hasMany avec le modèle d'entrée. Dans le même temps, nous avons également mis en place une condition ('Entry.read' => false) qui garantit que seuls les messages non lus sont retournés.

En second lieu, nous pouvons appeler une découverte sur le modèle RSS, réglage de la condition que le Feedfolder doit appartenir à l'utilisateur actuel.

+0

C'est de 90% du chemin pour ce que j'ai besoin, et il est de ma faute pour ce que je déformant en fait voulu. J'ai besoin d'obtenir le nombre d'entrées non lues groupées par l'identifiant du flux. Ce code peut-il être adapté à cela? – theraccoonbear

+0

@theraccoonbear - Voir ma nouvelle réponse. C'est un peu long, mais ça fait l'affaire. J'espère que ça marche pour toi. Moz –

0

Essayons à nouveau. Cette fois, je travaille directement depuis le contrôleur Entries.

/** 
* Unbind the existing relationship with Feed 
*/ 
$this->Entry->unbindModel(array(
    'belongsTo' => array('Feed') 
)); 

/** 
* Explicitly bind of the 'parent' models 
*/ 
$this->Entry->bindModel(array(
    'hasOne' => array(
    'Feed' => array(
     'foreignKey' => false, 
     'conditions' => array('Feed.id = Entry.feed_id') 
    ), 
    'Feedfolder' => array(
     'foreignKey' => false, 
     'conditions' => array('Feedfolder.id = Feed.feedfolder_id') 
    ), 
    'User' => array(
     'foreignKey' => false, 
     'conditions' => array('User.id = Feedfolder.user_id') 
    ) 
) 
)); 

/** 
* Find the entries that are unread and belong to the current user 
* and then Group by Feed.id 
*/ 
$unread = $this->Entry->find('all', array(
    'fields' => array(
    'Feed.Title', 
    'COUNT(Entry.id) AS UnreadCount' 
), 
    'conditions' => array(
    'Entry.read' => 0, 
    'User.id' => $this->Auth->user('id') 
), 
    'group' => array(
    'Feed.id' 
) 
)); 

Que se passe-t-il ici?

Tout d'abord, nous dissocions le modèle .

En second lieu, on lie explicitement la entrée modèle avec RSS, Feedfolder et utilisateur modèles. Cela empêche Cake d'essayer d'utiliser son bonté automagique (ce qui est encore très bien).

Enfin, nous appelons une découverte sur le modèle d'entrée et mis en place nos conditions requises: entrées non lus et appartiennent à l'utilisateur actuel. Nous regroupons ensuite tout par le Feed.id.

0

essayer cette

$this->Category->bindModel(
      array('belongsTo' => array(
        'ParentCategory' => array('className' => 'Category', 

'foreignKey' => 'parent_id'), 
    )));