Могу ли я отсортировать дочерние элементы, отличные от родительских, в многопоточном запросе CakePHP 3?
У меня есть вопросы по поводу комментариев. Можно ли заказать комментарии 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();
`` `
1 ответ
На уровне SQL
Вы должны быть в состоянии применить решение, предложенное в MySql: ORDER BY parent and child, которое
- использования
COALESCE
сначала сгруппировать / отсортировать родителей - группирует детей путем тестирования на
NULL
ID родителя - сортирует сгруппированных детей
В вашем случае вы бы сортировать по created
вместо id
то есть что-то вроде
ORDER BY
COALESCE(Comments.parent_id, Comments.created) DESC,
Comments.parent_id IS NOT NULL,
Comments.created ASC
Чтобы построить это в правильном стиле построения запросов, вам нужно использовать 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();
Смотрите также
- Кулинарная книга> Доступ к базе данных и ORM > Построитель запросов> Выбор данных
- Кулинарная книга> Доступ к базе данных и ORM > Построитель запросов> Использование функций SQL
- Кулинарная книга> Доступ к базе данных и ORM > Построитель запросов> Дополнительные условия
На уровне 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();
Это будет получать все сортировать по убыванию, а затем сортировать все children
массивы по возрастанию created
поле. Точно так же вы можете сортировать вещи перед тем, как выводить / использовать их в своих представлениях, в зависимости от того, что именно вы планируете делать с результатами.
Если вы хотите сохранить все в таблице, вы можете, например, обернуть все это в пользовательском искателе и / или получить закрытие сортировки с помощью метода вашего класса таблицы.
Смотрите также