如何在CakePHP查找查询中正确嵌套自定义字段?

我们经常处理类似如下的代码:

return $this->find(
'all', [
  'fields' => ['DISTINCT Tag.tag', 'COUNT(Tag.tag) as count'],
  'group' => ['Tag.tag'],
  'order' => ['count' => 'DESC']
]);

此查询引导我们进行以下输出:

[0] => Array
    (
        [Tag] => Array
            (
                [tag] => walls.io
            )

        [0] => Array
            (
                [count] => 15
            )

    )

如您所见,查询以“某种方式错误”嵌套返回结果.遗憾的是,“count”字段被放入伪[0] – 阵列中.

IIRC,CakePHP在内部使用像Tag__field这样的语法来正确嵌套虚拟字段.

将代码更改为Model __-语法时,问题保持不变:

return $this->find(
'all', [
  'fields' => ['DISTINCT Tag.tag', 'COUNT(Tag.tag) as Tag__count'],
  'group' => ['Tag.tag'],
  'order' => ['COUNT(Tag.tag)' => 'DESC']
]);

输出:

[0] => Array
    (
        [Tag] => Array
            (
                [tag] => walls.io
            )

        [0] => Array
            (
                [Tag__count] => 15
            )

    )

解决方法1:array_map

CakePHP专业人士:有没有比select语句后手动映射数组更好/更优雅的解决方案?

$tags = array_map(function($tag) {
  $tag['Tag']['count'] = $tag[0]['count'];
  unset($tag[0]);

  return $tag;
}, $tags);

解决方法2:虚拟字段

如上所述,虚拟字段的使用可以解决此问题:

$this->virtualFields = ['count' => 'COUNT(Tag.Tag)'];
return $this->find(
'all', [
  'group' => ['Tag.tag'],
  'order' => [$this->getVirtualField('count') => 'DESC']
]);

不幸的是,使用此解决方案,根本无法指定任何字段.只有完全离开“fields”-key,数组的嵌套才能按预期工作.当选择$fields = [‘Tag.tag’,$this-> getVirtualField(‘count’)]时,嵌套再次出错.

CakePHP专业人员:你知道一个方法,即使你指定自己的字段,嵌套也是正确的吗?

最佳答案
看看CakePHP代码,这样的方法不存在.

看看文件lib / Cake / Model / Datasource / Database / Mysql.php.

找到名为的方法:Mysql :: resultSet($results); (约line 240).

该方法将结果映射到数组.要确定列是否是表的一部分,它使用PDOStatement :: getColumnMeta().对于您的“虚拟列”,该方法将返回一个空表,因此CakePHP代码将单独放置它,请参阅else分支

$this-> map [$index] = array(0,$column [‘name’],$type);

为了避免使用其他分支,您必须使用虚拟字段,但之后会遇到您注意到的其他问题.

所以你留下了array_map解决方案,或者你可以尝试重载那个Mysql类,并添加你的自定义逻辑来确定列适合的位置.

转载注明原文:如何在CakePHP查找查询中正确嵌套自定义字段? - 代码日志