Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jrdavidson's avatar

Using MapToGroups for collections

Currently, I have a collection of users I"m passing into the getUsers function. What my goal is to loop over each item in the collection and then group those by their user type.

I have an additional level somehow with my current implementation and thought about flattening but that isn't really the route to go I'd rather make sure that what I get back from getUsers is in the correct format.

public static function getUsers(Collection $users)
{
    $formattedUsers = collect();

    foreach ($users as $sideNumber => $sideUsers) {
        $students = collect();
        $teachers = collect();

        foreach ($sideUsers as $user) {
            if ($user['user_type'] === 'student') {
                $student = Student::find($user['user_id']);
                $formattedUsers[$sideNumber]['students'] = collect($students->push($student));
            } elseif ($user['user_type'] === 'teacher') {
                $teacher = Teacher::find($user['user_id']);
                $formattedUsers[$sideNumber]['teachers'] = collect($teachers->push($teacher));
            }
        }
    }

    return $formattedUsers;
}

Collection of Users passed into getUsers function

Illuminate\Support\Collection^ {#2726
  #items: array:2 [
    0 => array:4 [
      0 => array:2 [
        "user_type" => "student"
        "user_id" => 1
      ]
      1 => array:2 [
        "user_type" => "student"
        "user_id" => 2
      ]
      2 => array:2 [
        "user_type" => "teacher"
        "user_id" => 5
      ]
      3 => array:2 [
        "user_type" => "teacher"
        "user_id" => 6
      ]
    ]
    1 => array:4 [
      0 => array:2 [
        "user_type" => "student"
        "user_id" => 3
      ]
      1 => array:2 [
        "user_type" => "student"
        "user_id" => 4
      ]
      2 => array:2 [
        "user_type" => "teacher"
        "user_id" => 7
      ]
      3 => array:2 [
        "user_type" => "teacher"
        "user_id" => 8
      ]
    ]
  ]
  #escapeWhenCastingToString: false
}

Expecting

collection
  0 => groupOneCollection
      'students' => collectionOfStudents
      'teachers' => collectionOfTeachers
  1 => groupTwoCollection
      'students' => collectionOfStudents
      'teachers' => collectionOfTeachers
0 likes
2 replies
webrobert's avatar
Level 51

I think this will do it...

getUsers(Collection $users)
{
    return $users->transform(function($group) {
        return collect($group)->transform( function ($user) {
            $user['type'] = $user['user_type'] === 'teacher'
                ? Teacher::find($user['user_id'])
                : Student::find($user['user_id']);
            return $user;
        })->mapToGroups(function ($item) {
            return [$item['user_type' ].'s' => $item['type']];
        });
    });
});
1 like

Please or to participate in this conversation.