5

我是 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

1 回答 1

9

该格式几乎是一种反向包含,仅使用 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在每个图像结果上命名的计算字段,由包含的关键字组成,按相关的类别标题分组,关键字嵌套在一个数组中titlekeywords其中类别从关键字中删除,最后重新索引整个事物作为一个基本的数字索引数组。

也可以看看

于 2016-01-17T15:32:53.590 回答