首页 > 解决方案 > CakePHP Query Builder 的 case 语句导致 `array_combine()` 和类型错误

问题描述

我想使用查询生成器在 CakePHP 中编写以下查询:

SELECT
(CASE
    WHEN `ai` = 1 THEN CONCAT_WS(" ", `name`, " (AI)") ELSE `name`
END) AS `name`
FROM `drivers`;

我尝试了几种方法,但似乎总是失败。首先,我尝试了这个:

return $query->select(function(Query $query) {
    return $query->newExpr()->addCase([
            $query->newExpr()->add(['ai' => 1])
        ], [
            $query->newExpr()->add(['name' => 'CONCAT_WS(" ", `name`, " (AI)")'])
    ]);
});

我试过这个:

return $query->select(function(Query $query) {
    return $query->newExpr()->addCase([
            $query->newExpr()->add(['ai' => 1])
        ], [
            $query->newExpr()->add(['name' => $query->func()->concat([" ", 'name', " (AI)"])])
    ]);
});

但在这两种情况下,我都会收到此错误:

警告 (2): array_combine(): 两个参数应该有相同数量的元素 [CORE/src/ORM/ResultSet.php, line 528]

传递给 Cake\ORM\Entity::__construct() 的参数 1 必须是数组类型,bool 给定,在第 602 行的 /var/www/html/vendor/cakephp/cakephp/src/ORM/ResultSet.php 中调用

所以这两个结果都是相同的查询,但它仍然是错误的......

标签: phpcakephpcasequery-buildercakephp-3.x

解决方案


您没有选择任何别名,CASE表达式将按原样放在SELECT子句中,这是 ORM 不喜欢的,因为它尝试将选择列表键与检索到的行的键匹配。

这可能需要更好、更有帮助的错误消息,或者 ORM 甚至可能在编译查询时发出警告,不确定。

无论如何,长话短说,返回一个带有别名的数组,如下所示:

return $query->select(function(Query $query) {
    $case = $query->newExpr()->addCase(
        [
            // WHEN
            $query->newExpr()->add(['ai' => 1])
        ],
        [
            // THEN
            $query->func()->concat([' ', $query->identifier('name'), ' (AI)']),
            // ELSE
            $query->identifier('name')
        ]
    );

    return [
        'name' => $case,
    ];
});

另请注意,您需要直接传入CONCAT()函数表达式,不要将其包装在另一个将结果分配给某些东西的表达式中,那将不起作用。此外,您需要确保标识符是这样传递的,目前您的name值将绑定为带引号的字符串文字,并且您还需要该ELSE部分的第二个标识符值。

也可以看看


推荐阅读