CakePHP 3.4:查询在哪里或匹配

时间:2017-04-12 10:52:53

标签: cakephp cakephp-3.4

我阅读了cookbook,但我无法弄清楚如何在单个查询中合并matching()orWhere()

示例:我Photo属于Album。两者都有active字段。所以我正在尝试编写findInactive()方法。 “非活动”照片的active字段false active字段为false的相册相匹配。

这样的事情:

public function findInactive(Query $query, array $options)
{
    $query->matching('Albums', function ($q) {
            return $q->where(['Albums.active' => false]);
        })
        ->orWhere(['Photos.active' => false])
        ->enableAutoFields(true);

    return $query;
}

但这不起作用:

'SELECT [...] FROM photos Photos INNER JOIN photos_albums Albums ON (Albums.active = :c0 AND Albums.id = (Photos.album_id)) WHERE Photos.active = :c1'

怎么办?感谢。

修改

也许可能的解决方案是使用contain()

    $query->contain(['Albums => ['fields' => ['active']]])
        ->where(['Photos.active' => false])
        ->orWhere(['Albums.active' => false]);

但是无法使用matching()innerJoinWith()吗?

1 个答案:

答案 0 :(得分:0)

将条件添加到主查询

带有条件的

matching()innerJoinWith()是错误的方法,因为条件被添加到INNER连接ON子句中,这将导致{Photo连接1}} Albums.active条件不匹配时要排除的行。

如果您只想接收属于相册的照片,则需要使用matching()innerJoinWith(),但您必须将条件添加到主查询中,即:

$query
   ->innerJoinWith('Albums')
   ->where(['Albums.active' => false])
   ->orWhere(['Photos.active' => false])
   // ...

如果照片不必属于某个相册,或者它是否属于相册并不重要,则可以使用leftJoin()leftJoinWith()甚至contain()

后者可能会使用INNER joinStrategy和/或select strategy(使用单独的查询),因此您需要照顾确保它使用LEFTjoin代替。但是,如果你真的想要包含某些内容,通常只会建议使用包含,并且考虑到你的查找器似乎只是过滤器,我会说leftJoinWith()代替:

$query
   ->leftJoinWith('Albums')
   ->where(['Albums.active' => false])
   ->orWhere(['Photos.active' => false])
   // ...

另见