Cakephp 3.0 - 案例语句的查询生成器

Cakephp 3.0 - Query builder for case statements

我按照蛋糕的食谱php 3 创建了一个case语句 http://book.cakephp.org/3.0/en/orm/query-builder.html#case-statements

但结果 sql 查询与预期不符。语句的 'Else' 部分缺失

这是我的代码:

$query = $this->Attendees->find()->contain(['Users']);
$lastModifedCase = $query->newExpr()->addCase($query->newExpr()->add(['Attendees.modified <' => 'Users.modified']), [ 'Users.modified', 'Attendees.modified'], 'datetime');
$query->select(['Attendees.id', 'lastModified' => $lastModifedCase, 'Users.firstName', 'Users.lastName']);

die(var_dump($query->__debugInfo()));

在debugInfo中,这是我能看到的sql:

array(13) {
  ["sql"]=>
  string(265) "SELECT Attendees.id AS `Attendees__id`, (CASE WHEN Attendees.modified < :c0 THEN :c1 END) AS `lastModified`, Users.firstName AS `Users__firstName`, Users.lastName AS `Users__lastName` FROM attendees Attendees INNER JOIN users Users ON Users.id = (Attendees.user_id)"
  ["params"]=>
  array(2) {
    [":c0"]=>
    array(3) {
      ["value"]=>
      string(14) "Users.modified"
      ["type"]=>
      string(8) "datetime"
      ["placeholder"]=>
      string(2) "c0"
    }
    [":c1"]=>
    array(3) {
      ["value"]=>
      string(14) "Users.modified"
      ["type"]=>
      string(8) "datetime"
      ["placeholder"]=>
      string(2) "c1"
    }
  }
  ["defaultTypes"]=>
  array(8) {
    ["Attendees.id"]=>
    string(7) "integer"
    ["id"]=>
    string(7) "integer"
    ["Attendees.user_id"]=>
    string(7) "integer"
    ["user_id"]=>
    string(7) "integer"
    ["Attendees.created"]=>
    string(8) "datetime"
    ["created"]=>
    string(8) "datetime"
    ["Attendees.modified"]=>
    string(8) "datetime"
    ["modified"]=>
    string(8) "datetime"
  }

"funny" 是食谱中的示例包含错误(变量 $unpublishedCase 应该是 $notPublishedCase)并且也没有给我预期的结果。这是它的 debugInfo(ps:我只是用我的与会者 table 替换了“$this->article”来测试这个例子)

array(13) {
  ["sql"]=>
  string(190) "SELECT (SUM(CASE WHEN published = :c0 THEN :c1 END)) AS `number_published`, (SUM(CASE WHEN published = :c2 THEN :c3 END)) AS `number_unpublished` FROM attendees Attendees GROUP BY published "
  ["params"]=>
  array(4) {
    [":c0"]=>
    array(3) {
      ["value"]=>
      string(1) "Y"
      ["type"]=>
      NULL
      ["placeholder"]=>
      string(2) "c0"
    }
    [":c1"]=>
    array(3) {
      ["value"]=>
      int(1)
      ["type"]=>
      string(7) "integer"
      ["placeholder"]=>
      string(2) "c1"
    }
    [":c2"]=>
    array(3) {
      ["value"]=>
      string(1) "N"
      ["type"]=>
      NULL
      ["placeholder"]=>
      string(2) "c2"
    }
    [":c3"]=>
    array(3) {
      ["value"]=>
      int(1)
      ["type"]=>
      string(7) "integer"
      ["placeholder"]=>
      string(2) "c3"
    }
  }
  ["defaultTypes"]=>
  array(8) {
    ["Attendees.id"]=>
    string(7) "integer"
    ["id"]=>
    string(7) "integer"
    ["Attendees.user_id"]=>
    string(7) "integer"
    ["user_id"]=>
    string(7) "integer"
    ["Attendees.created"]=>
    string(8) "datetime"
    ["created"]=>
    string(8) "datetime"
    ["Attendees.modified"]=>
    string(8) "datetime"
    ["modified"]=>
    string(8) "datetime"
  }

当我深入蛋糕php代码时,我认为我的问题来自Cake\Database\Expression\CaseExpression的构造函数:

public function __construct($conditions = [], $values = [], $types = [])
    {

        if (!empty($conditions)) {
            $this->add($conditions, $values, $types);
        }

        if (is_array($conditions) && is_array($values) && count($values) > count($conditions)) {
            end($values);
            $key = key($values);
            $this->elseValue($values[$key], isset($types[$key]) ? $types[$key] : null);
        }
    }

$conditions不被认为是一个数组,所以没有设置else值。

cakephp的版本是3.0.1

php的版本是5.4.34

大家怎么看?我做错了什么还是错误?

在此先感谢您的指教

当您使用数组语法生成条件时,您需要记住数组的值 par 将始终被视为参数而不是原始字符串:

['field_name >' => 'this is just a value, not a raw string']

原因是它可以防止 SQL 注入攻击。要解决您的问题,请执行以下操作:

['Attendees.modified < Users.modified']

而不是这个:

['Attendees.modified <' => 'Users.modified']

晚安后我发现了我的错误,我与你分享......希望有一天它能帮助别人。

语法不正确,$condition 肯定不是数组。

$lastModifedCase = $query->newExpr()->addCase(
    $query->newExpr()->add([
        'Attendees.modified <' => 'Users.modified'
    ]),
    ['Users.modified', 'Attendees.modified'],
    'datetime'
);

正确的语法是:

$lastModifedCase = $query->newExpr()->addCase(
    [$query->newExpr()->add('Attendees.modified < Users.modified')], 
    [ 'Users.modified', 'Attendees.modified'], 
    ['datetime','datetime']
);

我也:

  • 根据 José Lorenzo 的回答调整了条件
  • 指定了每个值的类型('datetime' 的数组代替 一个字符串)。否则,我得到一个 "wrong type" 错误。