CakePHP 3 - 无法生成具有 WHERE...OR 条件的查询

CakePHP 3 - unable to generate a query with WHERE...OR conditions

蛋糕PHP3.7

我正在尝试生成一个使用 WHERE...OR 模式的查询。 MySQL 中的等效项 - 执行并给出我想要的结果是:

SELECT * FROM groups Groups WHERE (regulation_id = 1 AND label like '%labelling%') OR (id IN(89,1,8,232,228,276,268,294));

我已阅读文档的高级条件 (https://book.cakephp.org/3.0/en/orm/query-builder.html#advanced-conditions) 部分,但无法生成该查询。

假设 Table class 是 Groups 我有这个:

$Groups = TableRegistry::getTableLocator()->get('Groups');

$groups_data = $Groups->find('all')->where(['regulation_id' => 1);

$groups_data = $groups_data->where(['label LIKE' => '%labelling%']);

这将生成 WHERE 语句的第一段,即

SELECT * FROM groups Groups WHERE (regulation_id = 1 AND label like '%labelling%')

但是我看不到如何附加 OR 条件,尤其是因为 orWhere() 已被弃用。

所以我试过了 - 这甚至在文档中作为示例给出:

$in_array = [89,1,8,232,228,276,268,294]; // ID's for IN condition

$groups_data = $groups_data->where(['OR' => ['id IN' => $in_array]]);

但这只是将 AND 附加到我现有的 SQL:

的内部
SELECT * FROM groups Groups WHERE (regulation_id = 1 AND label like '%labelling%' AND id IN(89,1,8,232,228,276,268,294);

这不会产生正确的结果,因为语法不是 运行 此查询所需的语法。

如何 WHERE 的 "move out" 并附加一个 OR 条件,就像普通查询中那样?

我根据文档使用 QueryExpression 进行了多次尝试,但所有这些都产生了 PHP 致命错误,说明与 Table class 有关 - 我怀疑这是否正确。

"moving out" 有点棘手,你必须明白在内部条件被推入一个 \Cake\Database\Expression\QueryExpression 对象,默认情况下使用 AND 连接语句,所以无论你继续下去,将使用 AND.

添加

当您创建 OR 语句时,无论是隐含地使用所示的嵌套数组语法,还是显式地使用表达式生成器,这都会创建一个单独的、自包含的表达式,其中其部分使用OR,它将自行编译(因为只有一个条件,你看不到任何 OR),结果将用于父表达式,在你的情况下是main/base 查询 where 子句的表达式对象。

一次传递整个东西(通过数组语法或表达式),例如:

$groups_data->where([
    'OR' => [
        'AND' => [
            'regulation_id' => 1,
            'label LIKE' => '%labelling%'
        ],
        'id IN' => $in_array
    ]
]);

当然,如果需要,您可以动态构建该数组,或者,如果您出于某种原因需要单独调用 where(),例如,您可以覆盖条件([=18 的第三个参数=]),并在您需要的地方包括当前的:

$groups_data->where(
    [
        'OR' => [
            $groups_data->clause('where'),
            'id IN' => $in_array
        ]
    ],
    [], 
    true
);

我知道这个问题已经过时了,但也许有人正在寻找。这是我的解决方案:

protected $_hardValues= array(
    'company_id' => $company_from_session;
);
function beforeFind($event=null, $query = null, $options = null, $primary = true){
    $conds = [];
    $columns = $this->getSchema()->columns();
    foreach( $this->_hardValues as $field => $value){
        if( !is_null($value) && in_array($field, $columns) ){
            $conds[$this->_alias . '.' . $field] = $value;
        }
    }
    if( empty( $conds)) return true;
    $where = $query->clause('where'); //QueryExpression object;
    if( empty( $where)){
        $query->where($conds);
    }else{
        $where->add($conds);
    }
}

自 CakePHP 4.x 起,记录在案的执行此操作的方法是:

$query = $articles->find()
->where([
    'author_id' => 3,
    'OR' => [['view_count' => 2], ['view_count' => 3]],
]);

documentation