我们经常处理如下代码:
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
)
)
如您所见,查询以“某种程度上错误”的嵌套形式返回结果。不幸的是,“计数”字段被放入伪 [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 = ['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);
为了避免 else 分支,您必须使用虚拟字段,但随后您会遇到您注意到的其他问题。
所以您只剩下 array_map 解决方案,或者您可以尝试重载该 Mysql 类并添加您的自定义逻辑来确定列适合的位置。
关于php - 如何在 CakePHP 查找查询中正确嵌套自定义字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21410237/