使用Model-> find()(CakePHP)的关联模型中的条件

时间:2009-11-17 20:52:50

标签: cakephp model associations

我在CakePHP的find()方法和'更深层'模型关联中遇到了一些问题。有一些这些,但到目前为止我找不到答案。

我的模型关联分别为User hasMany Post hasMany Comment hasMany VoteVote belongsTo Comment belongsTo Post belongsTo UserbelongsTo关联使用内部联接('type'=>'INNER')。

如何使用CakePHP的model-> find()方法查找特定用户帖子的所有评论投票?

我故意使用了四个模型链,因为这似乎适用于直接关联模型中的条件。所以没有在相邻表中使用外键保持列(条件'Post.user_id == 1'而不是'User.id == 1')。

在SQL中,这将是:

SELECT v.* 
FROM votes v 
    JOIN comments c ON (v.comment_id = c.id)
    JOIN posts p ON (c.post_id = p.id)
    JOIN users u ON (p.user_id = u.id)
WHERE u.id = 1

我无法使用find()+ Containable行为重现这些连接。虽然我可以简单地让用户获得他所有的数据,但我必须从结果数组中收集所有投票。

它不是这样的(警告:未知列'User.id'):

$this->Vote->recursive = 2; // or higher
$this->Vote->find('all',array('conditions' => array('User.id' => 1)));

事实上,只要我添加条件,这甚至不能使用Post而不是User(Vote-> Comment-> Post)。制造的SQL查询仅加入投票和评论。

返回的数组应该只包含上面的SQL查询将返回的投票,其他所有内容都应该在此过程中“加入”。

注意:我的问题非常接近这个,这帮助我入门: In cakephp how can I do a find with conditions on a related field?

4 个答案:

答案 0 :(得分:16)

$joins = array(
           array('table'=>'comments', 
                 'alias' => 'Comment',
                 'type'=>'inner',
                 'conditions'=> array(
                 'Comment.id = Vote.comment_id'
           )),
           array('table'=>'posts', 
                 'alias' => 'Post',
                 'type'=>'inner',
                 'conditions'=> array(
                 'Post.id = Comment.post_id'
           )),
           array('table'=>'users', 
                 'alias' => 'User',
                 'type'=>'inner',
                 'conditions'=> array(
                 'User.id = Post.user_id','User.id'=>$user_id
           ))
         );

$votes = $this->Vote->find('all',array('joins'=>$joins,'recursive'=>-1));

答案 1 :(得分:7)

使用Containable行为在关联的模型上执行条件。我花了一点时间来挖掘它,但它就像一个魅力!并且它使用LEFT JOIN,因此它仍将拉入原始模型的所有值。

See documentation

这样的事情应该有效:

$this->Vote->Behaviors->attach('Containable');
$this->Vote->find('all',array(
                            'contain'=>array(
                                'Comment'=>array(
                                    'Post'=>array(
                                        'User'=>array(
                                            'conditions'=>array(
                                                'User.id'=>1,
                                            ),
                                        ),
                                    ),
                                ),
                            ),
                        ));

如果您想要包含投票人的用户数据,您只需在初始数组中再添加一项:

$this->Vote->Behaviors->attach('Containable');
$this->Vote->find('all',array(
                            'contain'=>array(
                                'Comment'=>array(
                                    'Post'=>array(
                                        'User'=>array(
                                            'conditions'=>array(
                                                'User.id'=>1,
                                            ),
                                        ),
                                    ),
                                ),
                                'User',
                            ),
                        ));

希望有所帮助!

答案 2 :(得分:1)

这可能是您需要使用query method的时间之一。

  

你不能或不想通过其他模型方法进行的SQL调用(小心 - 很少有情况这是真的)可以使用模型的query()方法进行。

$votes = $this->Vote->query('SELECT Vote.* FROM votes Vote 
    JOIN comments Comment ON (Vote.comment_id = Comment.id)
    JOIN posts Post ON (Comment.post_id = Post.id)
    JOIN users User ON (Post.user_id = User.id)
    WHERE User.id = 1');

这应该返回一个投票条目数组,就像find方法一样。

foreach ($votes as $vote):
    echo $vote['Vote']['id'];
endforeach;

答案 3 :(得分:0)

您可以显式连接表,而不是执行自定义SQL查询,以便按间接关联表的字段进行筛选。请查看此页面,了解如何通过评论加入投票和用户: http://book.cakephp.org/view/872/Joining-tables