CakePHP 3: изменение структуры набора результатов

Я новичок в CakePHP и имею следующую проблему:

У меня есть таблицы «Изображения», «Ключевые слова» и «Ключевые слова». Каждое изображение может иметь много ключевых слов (много ко многим), и у каждого ключевого слова есть категория (много к одному). Получение списка изображений с

$images = $this->Images->find()->contain(['Keywords',  'Keywords.KeywordCategories']);

возвращает структуру результата как это:

[
{
"id":1,
"keywords":[
{
"keyword":"Dog",
"keyword_category":{
"title":"Animal"}
},
{
"keyword":"Cat",
"keyword_category":{
"title":"Animal"}
},
{
"keyword":"Black",
"keyword_category":{
"title":"Color"}
}
]
}
]

Это нормально, но я хочу, чтобы ключевые слова были сгруппированы по категориям ключевых слов в такой структуре:

[
{
"id":1,
"keyword_categories":[
{
"title":"Animal",
"keywords":[
{
"keyword":"Dog"},
{
"keyword":"Cat"}
]
},
{
"title":"Color",
"keywords":[
{
"keyword":"Black"}
]
}
]
}
]

Любая идея, как я могу добиться этого с помощью запроса CakePHP?

4

Решение

Этот формат в значительной степени является перевернутым содержимым, что невозможно при использовании только автоматической магии ассоциации ORM. Вы должны были бы выбрать связанные данные отдельно, отфильтровать их и вставить их в результаты изображения … вы могли бы даже создать собственный класс ассоциации, который содержит, выбирает и объединяет результаты вместе, но это своего рода излишество, если вы спросите мне.

Так как вам все равно придется делать дополнительное форматирование (и это просто для сшивания результатов), я бы просто использовал вместо этого некоторое форматирование коллекции foo, что-то вроде

// ...
->find()
->contain(['Keywords', 'Keywords.KeywordCategories'])
->formatResults(function ($results) {
/* @var $results \Cake\Datasource\ResultSetInterface|\Cake\Collection\CollectionInterface */
return $results->map(
function ($image) {
$image['keyword_categories'] =
collection($image['keywords'])
->groupBy('keyword_category.title')
->map(function ($keywords, $category) {
foreach ($keywords as &$keyword) {
unset($keyword['keyword_category']);
}
return [
'title' => $category,
'keywords' => $keywords
];
})
->toList();
unset($image['keywords']);
return $image;
}
);
});

* непроверенный пример кода для иллюстрации

т.е. создать вычисляемое поле с именем keyword_categories на каждом изображении результат, состоящий из содержащихся ключевых слов, сгруппированных по названию связанных категорий, с ключевыми словами, вложенными в массив с title а также keywords поля, в которых категория удаляется из ключевых слов, и, наконец, переиндексировать все это как базовый числовой индексированный массив.

Смотрите также

5

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector