我想用 cakephp4 的查询构建器做 "or where" 和 "concat"

I want to do "or where" and "concat" with the query builder of cakephp4

首先,我为我糟糕的英语道歉。

环境信息
语言:PHP 7.4.13
框架:蛋糕PHP 4.2.6

在 SQL 数据库 table,有 6 个列。
(columnA, columnB, columnC, columnD, columnE, columnF)

我想从连接的列中搜索。
我想用 4 个条件“或搜索”。

“${columnA}.${columnC}”是否匹配 $str
或者
'${columnB}.${columnC}' 是否匹配 $str
或者
'${columnD}.${columnF}' 是否匹配 $str
或者
'${columnE}.${columnF}' 是否匹配 $str

现在,我写成这样用一个条件搜索。

$query->where(function ($exp, $q) use($str) {
    $concat = $q->func()->concat([
        'columnA' => 'identifier', 
        'columnC' => 'identifier'
    ]);
    return $exp->like($concat, '%' . $str . '%' );
});

如果我从“非串联列”搜索,我会这样写。

$query->where([
    0 => [
        'or' => [
            '${columnA} LIKE' => '%' . $str . '%' ,
            '${columnB} LIKE' => '%' . $str . '%' ,
            '${columnC} LIKE' => '%' . $str . '%' ,
            '${columnD} LIKE' => '%' . $str . '%' ,
        ]
    ],

]);

最后,我想做这样的事情。(当然,这会引发语法错误)

$query->where([
    0 => [
        'or' => [
            '${columnA}.${columnC} LIKE' => '%' . $str . '%' ,
            '${columnB}.${columnC} LIKE' => '%' . $str . '%' ,
            '${columnD}.${columnF} LIKE' => '%' . $str . '%' ,
            '${columnE}.${columnF} LIKE' => '%' . $str . '%' ,
        ]
    ],

]);

有人可以帮助我吗?

查询表达式对象有一个您可以使用的 or() 方法,它要么采用使用 OR 组合的条件数组,要么采用接收新查询表达式对象的可调用对象使用 OR 运算符。

无论如何你需要知道QueryExpression::like()不会return一个新的表达式对象,但是它会添加一个新的like表达式到当前查询表达式对象的堆栈。

也就是说,回调变体看起来像这样:

$query->where(function (
    \Cake\Database\Expression\QueryExpression $exp,
    \Cake\ORM\Query $q
) use (
    $str
) {
    return $exp->or(function ($exp) use ($q, $str) {
        $concatAC = $q->func()->concat([
            'columnA' => 'identifier',
            'columnC' => 'identifier'
        ]);
        $concatBC = $q->func()->concat([
            'columnB' => 'identifier', 
            'columnC' => 'identifier'
        ]);
        
        return $exp
            ->like($concatAC, '%' . $str . '%')
            ->like($concatBC, '%' . $str . '%')
            // ...
    });
});

前一个变体可以通过传递一个空数组来使用,这样您会收到一个空的查询表达式对象,然后您可以用您的条件填充该对象:

$query->where(function (
    \Cake\Database\Expression\QueryExpression $exp,
    \Cake\ORM\Query $q
) use (
    $str
) {
    // ...

    return $exp
        ->or([])
        ->like($concatAC, '%' . $str . '%')
        ->like($concatBC, '%' . $str . '%')
        // ...
});

最后,您还可以随时更改用于连接任何查询表达式对象的表达式的字符串,使用 QueryExpression::setConjunction():

$query->where(function (
    \Cake\Database\Expression\QueryExpression $exp,
    \Cake\ORM\Query $q
) use (
    $str
) {
    // ...

    return $exp
        ->setConjunction('OR')
        ->like($concatAC, '%' . $str . '%')
        ->like($concatBC, '%' . $str . '%')
        // ...
});

所有三个变体将产生相同的 SQL,即:

WHERE (
    CONCAT(columnA, columnC) LIKE %...% OR
    CONCAT(columnB, columnC) LIKE %...% OR
    ...
)

另见