CakePHP 3.3.15 多重匹配()与 OR 链接
CakePHP 3.3.15 multiple matching() chained with OR
我正在尝试在我的 CakePHP 3.3.15 应用程序中实施全局搜索机制 - 这涉及搜索父 table 的值以及搜索所有关联 tables 相同的值。我正在使用 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
到目前为止我还尝试了什么:
- 使用
innerJoinWith()
而不是 matching() - 相同的结果,只是结果集缺少相关字段(完全如 CookBook 中所述)
- 使用
$this->$modelName->find()->contain('ChildTable', function ($q) { return $q->where(['ChildTable.FieldName' => 'some value']});
- 这似乎根本不起作用(不过滤结果集)
- 手动组合结果集以强制执行 OR 行为 - 我稍后在代码中使用分页,所以我无法直接处理结果集 - 我需要一个 Query 对象传递给分页器。
非常感谢任何帮助!
匹配将在 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
您要查找的内容需要使用 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');
由于联接的性质,您可能还需要对主模型的主键进行分组以避免重复结果。
另见
我正在尝试在我的 CakePHP 3.3.15 应用程序中实施全局搜索机制 - 这涉及搜索父 table 的值以及搜索所有关联 tables 相同的值。我正在使用 matching()
,但我找不到使用 OR.
看起来 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
到目前为止我还尝试了什么:
- 使用
innerJoinWith()
而不是 matching() - 相同的结果,只是结果集缺少相关字段(完全如 CookBook 中所述) - 使用
$this->$modelName->find()->contain('ChildTable', function ($q) { return $q->where(['ChildTable.FieldName' => 'some value']});
- 这似乎根本不起作用(不过滤结果集) - 手动组合结果集以强制执行 OR 行为 - 我稍后在代码中使用分页,所以我无法直接处理结果集 - 我需要一个 Query 对象传递给分页器。
非常感谢任何帮助!
匹配将在 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
您要查找的内容需要使用 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');
由于联接的性质,您可能还需要对主模型的主键进行分组以避免重复结果。
另见