Search code examples
phplaraveleloquentcollectionsgrouping

Laravel collection group by multi keys


I am currently trying to group multiple rows into different keys on an array depending on the dates which are supplied.

The kind of data which I have is the following

| id | attendees | start_date          | end_date            |
| 1  | 23        | 2020-01-01 12:00:00 | 2020-01-01 13:00:00 |
| 2  | 24        | 2020-01-01 12:00:00 | 2020-01-01 13:00:00 |
| 3  | 54        | 2020-01-01 13:30:00 | 2020-01-01 14:00:00 |
| 4  | 24        | 2020-01-01 15:00:00 | 2020-01-01 17:00:00 |
| 5  | 24        | 2020-01-01 13:30:00 | 2020-01-01 14:00:00 |

I want to be able to group the different columns but still have access to all of the attributes in a multi dimensional array.

The result will look something like the following:

[
   [
      [
         'start_date' => '2020-01-01 12:00:00',
         'end_date' => '2020-01-01 13:00:00',
         'attendees' => 23
      ],
      [
         'start_date' => '2020-01-01 12:00:00',
         'end_date' => '2020-01-01 13:00:00'
         'attendees' => 24
      ]

   ],
   [
      [
         'start_date' => '2020-01-01 13:30:00',
         'end_date' => '2020-01-01 14:00:00',
         'attendees' => 54
      ],
      [
         'start_date' => '2020-01-01 13:30:00',
         'end_date' => '2020-01-01 14:00:00',
         'attendees' => 24
      ]
   ],
   [
      [
         'start_date' => '2020-01-01 15:00:00',
         'end_date' => '2020-01-01 17:00:00',
         'attendees' => 24
      ]

   ]
]

I have tried to reduce the collection result from the original query

$attendees = Attendee::query()->whereDate('start_date', '2020-01-01')->get();

$attendees->reduce(function ($carry, $attendee) {
    return $carry;
}, []);

But I am unsure on what to do when searching in the existing array.

I have tried to do Laravel built in collection method groupBy but that gives me an empty array or an error.


Solution

  • For this, you could use the Laravel Collection groupBy() method:

    $attendees = Attendee::query()->whereDate('start_date', '2020-01-01')->get();
    
    
    $groupedAttendees = $attendees->groupBy(function (Attendee $attendee) {
        return $attendee->start_date->toString() . '-' . $attendee->end_date->toString();
    })->values();
    

    values() is used to remove the [start_date]-[end_date] key created by groupBy

    Please note this is not the same as groupBy() on the query builder.