如何重新排序集合

How to reorder a collection

来自以下查询:

$unlocked_ags = $this->Deviceconnections->find()
            ->contain(['Agthemes.Sites'])
            ->where(['request' => 'unlock'])->all();

我得到以下结果。我只是保留了有用的信息。

'items' => [
    (int) 0 => object(App\Model\Entity\Deviceconnection) {

        'id' => (int) 196,
        'agtheme' => object(App\Model\Entity\Agtheme) {

            'id' => (int) 49,
            'site' => object(App\Model\Entity\Site) {

                'id' => (int) 5510,
            },
        },
    },
    (int) 1 => object(App\Model\Entity\Deviceconnection) {

        'id' => (int) 197,
        'agtheme' => object(App\Model\Entity\Agtheme) {

            'id' => (int) 44,
            'site' => object(App\Model\Entity\Site) {

                'id' => (int) 64,
            },
        },
    },
    (int) 2 => object(App\Model\Entity\Deviceconnection) {

        'id' => (int) 198,
        'agtheme' => object(App\Model\Entity\Agtheme) {

            'id' => (int) 49,
            'site' => object(App\Model\Entity\Site) {

                'id' => (int) 5510,
                },
            },
        },
    },
    (int) 3 => object(App\Model\Entity\Deviceconnection) {

        'id' => (int) 199,
        'agtheme' => object(App\Model\Entity\Agtheme) {

            'id' => (int) 44,
            'site' => object(App\Model\Entity\Site) {

                'id' => (int) 5682,
                },
            },
        },
    },
    (int) 4 => object(App\Model\Entity\Deviceconnection) {

        'id' => (int) 200,
        'agtheme' => object(App\Model\Entity\Agtheme) {

            'id' => (int) 44,
            'site' => object(App\Model\Entity\Site) {

                'id' => (int) 5682,
                },
            },
        },
    },
    (int) 5 => object(App\Model\Entity\Deviceconnection) {

        'id' => (int) 201,
        'agtheme' => object(App\Model\Entity\Agtheme) {

            'id' => (int) 49,
            'site' => object(App\Model\Entity\Site) {

                'id' => (int) 5510,
                },
            },
        },
    },
    (int) 6 => object(App\Model\Entity\Deviceconnection) {

        'id' => (int) 202,
        },
        'agtheme' => object(App\Model\Entity\Agtheme) {

            'id' => (int) 40,
            },
            'site' => object(App\Model\Entity\Site) {

                'id' => (int) 64,
                },
            },
        },
    }
]

但实际上我想按站点和 agtheme 获得设备连接列表。

我完成了一半的查询:

$unlocked_ags = $this->Deviceconnections->find()
            ->contain(['Agthemes.Sites'])
            ->where(['request' => 'unlock'])
            ->groupBy('agtheme.site.id');

这让我可以按站点分组。

我需要这样的东西:

$unlocked_ags = $this->Deviceconnections->find()
            ->contain(['Agthemes.Sites'])
            ->where(['request' => 'unlock'])
            ->groupBy('agtheme.site.id')
            ->groupBy('agtheme.id');

不过看来我需要换一种方式来写了。

怎么做?

编辑 我试过类似的东西:

    $unlocked_ags = $this->Deviceconnections->find()
            ->contain(['Agthemes.Sites'])
            ->where(['request' => 'unlock']);

    $unlocked_ags = $unlocked_ags->groupBy('agtheme.site.id');
    $unlocked_ags = new Collection($unlocked_ags);
    $unlocked_ags = $unlocked_ags->groupBy('agtheme.id');

这正确地创建了分组数组,但不幸的是,它丢失了索引。

结果类似于:

[
    '' => [
        (int) 0 => [
            (int) 0 => object(App\Model\Entity\Deviceconnection) {
            ...

真可惜,因为如果我这样做:

    $unlocked_ags = $this->Deviceconnections->find()
            ->contain(['Agthemes.Sites'])
            ->where(['request' => 'unlock']);

    $unlocked_ags = $unlocked_ags->groupBy('agtheme.site.id');

我得到:

[
    (int) 5510 => [
        (int) 0 => object(App\Model\Entity\Deviceconnection) {
         ...

有什么想法吗?

如果您想要嵌套结果,则必须迭代第一个分组结果并再次对它们进行分组:

->groupBy('agtheme.site.id')
->map(function ($data) {
    return collection($data)->groupBy('agtheme.site')->toArray();
})

或使用回调创建基于多个字段的自定义标识符,例如:

->groupBy(function($row) {
    return $row['agtheme']['id'] . ',' . $row['agtheme']['site']['id'];
})

后者会创建类似 49,5510 的字符串索引,所以当 accessing/iterating 超过结果时要小心!

另见 API > \Cake\Collection\CollectionInterface::groupBy()