Laravel 多层 groupBy

问题描述

假设我们有这个记录:

---------------------------------------------------------
|   id  |   relation_id |   color       |   text        |
---------------------------------------------------------
|   1   |       1       |   /* null */  |   text_001    |
---------------------------------------------------------
|   2   |       1       |   /* null */  |   text_002    |
---------------------------------------------------------
|   3   |       2       |   /* null */  |   text_003    |
---------------------------------------------------------
|   4   |       2       |   /* null */  |   text_004    |
---------------------------------------------------------
|   5   |       3       |   /* null */  |   text_005    |
---------------------------------------------------------
|   6   |       3       |   /* null */  |   text_006    |
---------------------------------------------------------
|   7   |       4       |       red     |   text_007    |
---------------------------------------------------------
|   8   |       4       |       red     |   text_008    |
---------------------------------------------------------
|   9   |       4       |       green   |   text_009    |
---------------------------------------------------------
|   10  |       4       |       green   |   text_010    |
---------------------------------------------------------
|   11  |       4       |       blue    |   text_011    |
---------------------------------------------------------
|   12  |       4       |       blue    |   text_012    |
---------------------------------------------------------

假设我们的 DummyController 中有此代码

// take note,groupBy() is using a relation here
public function index(Dummy $dummy)
{
    $dummyRecord = $dummy->with('anotherModel')->get()->sortBy('relation_id')->groupBy('anotherModel.column_name');
    return view('index')->with('dummyRecord',$dummyRecord);
}

最后,假设我们的 @foreach ($dummyRecord as $dummy_column_name => $dummy) 中有 index.blade,我们可以这样显示结果:

// assume this is a div
---------------------
|   relation 1      |
---------------------
|       text_001    |
|       text_002    |
---------------------

// assume this is a div
---------------------
|   relation 2      |
---------------------
|       text_003    |
|       text_004    |
---------------------

// assume this is a div
---------------------
|   relation 3      |
---------------------
|       text_005    |
|       text_006    |
---------------------

// assume this is a div
---------------------
|   relation 4      |
---------------------
|       text_007    |
|       text_008    |
|       text_009    |
|       text_010    |
|       text_011    |
|       text_012    |
---------------------

但我想将relation 4的{​​{1}}记录显示为div内的div,这使得最终的输出color文件中如下所示:

index.blade

我应该使用另一个 // assume this is a div --------------------- | relation 1 | --------------------- | text_001 | | text_002 | --------------------- // assume this is a div --------------------- | relation 2 | --------------------- | text_003 | | text_004 | --------------------- // assume this is a div --------------------- | relation 3 | --------------------- | text_005 | | text_006 | --------------------- // assume this is a div --------------------------------------------- | relation 4 | --------------------------------------------- | | | // assume this is a div inside a div | | ----------------- | | | red | | | ----------------- | | | text_007 | | | | text_008 | | | ----------------- | | | | // assume this is a div inside a div | | ----------------- | | | green | | | ----------------- | | | text_009 | | | | text_010 | | | ----------------- | | | | // assume this is a div inside a div | | ----------------- | | | blue | | | ----------------- | | | text_011 | | | | text_012 | | | ----------------- | | | --------------------------------------------- 对颜色记录进行排序,还是可以在 groupBy 文件添加一个排序代码

解决方法

你可以使用集合[map()][1]来解决这个目的。

$dummy->with('anotherModel')
    ->get()
    ->sortBy('relation_id')
    ->groupBy('relation_id',true)
    ->map(function($q){
        // group by color
        return collect($q)->groupBy('color',true);
    })
    ->all();


  [1]: https://laravel.com/docs/8.x/collections#method-map
,

你可以这样group by multiple nested properties

$dummy
    ->with('anotherModel')
    ->get()
    ->sortBy('relation_id')
    ->groupBy(['anotherModel.column_name','anotherModel.anotherColumn_name']);

然后像这样在你的刀片上循环:

@foreach(/* ... */)
    <div>
        relation {{ $i }}
        @foreach(/* ... */)
            <div>
                {{ $color }}
                @foreach(/* ... */)
                   {{ $text}}
                @endforeach
            </div>
        @endforeach
    </div>
@endforeach