CakePHP 3.3.15 使用 OR 链接多个匹配()

Tom*_*Cz. 3 php cakephp associations query-builder cakephp-3.x

我正在尝试在CakePHP 3.3.15应用程序中实现全局搜索机制- 这涉及在父表中搜索值以及在所有关联表中搜索相同的值。我正在使用matching(),但我找不到一种使用 OR 将多个matching() 组合到一个查询对象中的方法。

看起来matching()会缩小结果集范围,并且连续调用matching()将使用先前matching()调用修改的对象。

这就是我所拥有的:

$query = $this->$modelName->find();         
$query->matching('Colonies', function ($q) {
                return $q->where(['OR' => [
                    'Colonies.colony_id' => 10003,
                    'Colonies.project_id' => 6
                ]]);
            });
debug($query->count()); //returns 4 entries

$query->matching('Projects', function ($q) {
                return $q->where(['OR' => [
                    'Projects.id' => 1,
                    'Projects.project_status_id' => 3
                ]]);
            });
debug($query->count()); //returns 1 entry. However, when the previous matching() is removed, it will return 2 entries
Run Code Online (Sandbox Code Playgroud)

到目前为止我还尝试过什么:

  1. 使用innerJoinWith()而不是matching() - 结果相同,只是结果集缺少关联字段(正如CookBook中所述)
  2. 使用$this->$modelName->find()->contain('ChildTable', function ($q) { return $q->where(['ChildTable.FieldName' => 'some value']});- 这似乎根本不起作用(不过滤结果集)
  3. 手动组合结果集以强制执行 OR 行为 - 我稍后在代码中使用分页,因此我无法直接处理结果集 - 我需要一个 Query 对象传递给分页器。

非常感谢任何帮助!

ndm*_*ndm 6

匹配将在JOIN级别上应用条件,因此每组matching()条件将独立应用,并且由于matching()创建INNER连接,两个连接都将排除记录。

检查生成的 SQL,您的多个matching()条件将创建类似于以下的 SQL:

INNER JOIN colonies ON colonies.colony_id = 10003 OR colonies.project_id = 6
INNER JOIN projects ON projects.id = 1 OR projects.project_status_id = 3
Run Code Online (Sandbox Code Playgroud)

您要查找的内容需要使用 A)LEFT连接,以便连接本身不会排除记录,B) 在主查询上应用条件,以便能够根据连接表过滤记录:

$query = $this->$modelName
    ->find()
    ->leftJoinWith('Colonies')
    ->leftJoinWith('Projects')
    ->where([
        'OR' => [
            'Colonies.colony_id' => 10003,
            'Colonies.project_id' => 6,
            'Projects.id' => 1,
            'Projects.project_status_id' => 3
        ]
    ])
    ->group($modelName . '.id');
Run Code Online (Sandbox Code Playgroud)

由于连接的性质,您可能还需要对主模型主键进行分组,以避免重复结果。

也可以看看