2

我阅读了食谱,但我不知道如何在单个查询中组合 amatching()和 a 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()orinnerJoinWith()吗?

4

1 回答 1

2

将条件添加到主查询

matching()or innerJoinWith()with conditions 是错误的方法,因为条件被添加到INNERjoins子句中,如果条件不匹配ON,这将导致该Photo行被排除。Albums.active

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

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

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

然而,后者可能使用INNER joinStrategyand/or the select strategy(使用单独的查询),因此您需要注意确保它使用LEFTandjoin代替。但是,通常仅在您确实想要包含某些东西时才建议使用容器,并且鉴于您的查找器似乎应该只是过滤东西,我会说leftJoinWith()改为:

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

也可以看看

于 2017-04-12T12:15:10.637 回答