我可以在 CakePHP 3 线程查询中对不同于父项的子项进行排序吗?
Can I sort children different than parent in CakePHP 3 threaded query?
我有一个关于线程评论的问题。是否可以从此查询(或 table 级别)订购评论 DESC 和子评论 ASC,或者我应该在查询修改后进行排序?
您可以在下面找到我的查询,该查询将全部订购到 DESC。
```
$comments = $this->Comments
->find('threaded', ['order' => ['Comments.created' => 'DESC']])
->contain(['Users'])
->matching(
'BoardItems',
function ($q) use ($boardItemId) {
return $q->where(
[
'BoardItems.id' => $boardItemId
]
);
}
)
->all();
```
在SQL级别
您应该能够应用 MySql: ORDER BY parent and child 中建议的解决方案,其中
- 首先使用
COALESCE
到 group/sort parent
- 通过测试非
NULL
parent ID 对children进行分组
- 对分组的 children
进行排序
在你的情况下,你会按 created
而不是 id
排序,例如
ORDER BY
COALESCE(Comments.parent_id, Comments.created) DESC,
Comments.parent_id IS NOT NULL,
Comments.created ASC
要以正确的查询 builder-ish 方式构建它,您必须使用 order()
和 orderDesc()
方法,以便您可以使用查询表达式,行
$query = $this->Comments
->find('threaded');
$comments = $query
// ->contain(...)
// ->matching(...)
// COALESCE(Comments.parent_id, Comments.created) DESC
->orderDesc($query->func()->coalesce([
'Comments.parent_id' => 'identifier',
'Comments.created' => 'identifier'
]))
// Comments.parent_id IS NOT NULL
->order($query->newExpr()->isNotNull('Comments.parent_id'))
// Comments.created ASC
->order(['Comments.created' => 'ASC'])
->all();
另见
- Cookbook > Database Access & ORM > Query Builder > Selecting Data
- Cookbook > Database Access & ORM > Query Builder > Using SQL Functions
- Cookbook > Database Access & ORM > Query Builder > Advanced Conditions
在PHP水平
事后排序也是一种选择,例如使用递归结果格式化程序:
$sortChildren = function($row) use (&$sortChildren) {
if (!empty($row['children'])) {
$row['children'] =
collection($row['children'])
->sortBy('created', SORT_ASC)
->map($sortChildren)
->toArray();
}
return $row;
};
$comments = $this->Comments
->find('threaded')
// ->contain(...)
// ->matching(...)
->order(['Comments.created' => 'DESC'])
->formatResults(function ($results) use ($sortChildren) {
return $results->map($sortChildren);
})
->all();
这将检索所有降序排序的内容,然后按 created
字段对所有 children
数组进行升序排序。类似地,您可以在视图中 output/use 之前对它们进行排序,具体取决于您打算如何处理结果。
如果您想将内容保留在 table 中,例如,您可以将其全部包装在自定义查找器中 and/or 通过 table 上的方法检索排序闭包class.
另见
我有一个关于线程评论的问题。是否可以从此查询(或 table 级别)订购评论 DESC 和子评论 ASC,或者我应该在查询修改后进行排序?
您可以在下面找到我的查询,该查询将全部订购到 DESC。
```
$comments = $this->Comments
->find('threaded', ['order' => ['Comments.created' => 'DESC']])
->contain(['Users'])
->matching(
'BoardItems',
function ($q) use ($boardItemId) {
return $q->where(
[
'BoardItems.id' => $boardItemId
]
);
}
)
->all();
```
在SQL级别
您应该能够应用 MySql: ORDER BY parent and child 中建议的解决方案,其中
- 首先使用
COALESCE
到 group/sort parent - 通过测试非
NULL
parent ID 对children进行分组
- 对分组的 children 进行排序
在你的情况下,你会按 created
而不是 id
排序,例如
ORDER BY
COALESCE(Comments.parent_id, Comments.created) DESC,
Comments.parent_id IS NOT NULL,
Comments.created ASC
要以正确的查询 builder-ish 方式构建它,您必须使用 order()
和 orderDesc()
方法,以便您可以使用查询表达式,行
$query = $this->Comments
->find('threaded');
$comments = $query
// ->contain(...)
// ->matching(...)
// COALESCE(Comments.parent_id, Comments.created) DESC
->orderDesc($query->func()->coalesce([
'Comments.parent_id' => 'identifier',
'Comments.created' => 'identifier'
]))
// Comments.parent_id IS NOT NULL
->order($query->newExpr()->isNotNull('Comments.parent_id'))
// Comments.created ASC
->order(['Comments.created' => 'ASC'])
->all();
另见
- Cookbook > Database Access & ORM > Query Builder > Selecting Data
- Cookbook > Database Access & ORM > Query Builder > Using SQL Functions
- Cookbook > Database Access & ORM > Query Builder > Advanced Conditions
在PHP水平
事后排序也是一种选择,例如使用递归结果格式化程序:
$sortChildren = function($row) use (&$sortChildren) {
if (!empty($row['children'])) {
$row['children'] =
collection($row['children'])
->sortBy('created', SORT_ASC)
->map($sortChildren)
->toArray();
}
return $row;
};
$comments = $this->Comments
->find('threaded')
// ->contain(...)
// ->matching(...)
->order(['Comments.created' => 'DESC'])
->formatResults(function ($results) use ($sortChildren) {
return $results->map($sortChildren);
})
->all();
这将检索所有降序排序的内容,然后按 created
字段对所有 children
数组进行升序排序。类似地,您可以在视图中 output/use 之前对它们进行排序,具体取决于您打算如何处理结果。
如果您想将内容保留在 table 中,例如,您可以将其全部包装在自定义查找器中 and/or 通过 table 上的方法检索排序闭包class.
另见