The Laravel way of separating items in a collection based on user_id

In the Event-model I have this relationship:

public function eventQuestionUsers(){ 
  return $this->hasMany( 'AppEventQuestionUsers' );
}

So when I get an $event in my Controller, I do this:
public function show( $event_id ){
  $user = Auth::user();
  $event = Event::where( [ 'id', '=', $event_id ] )->get();

  if( $user->can( 'manage', $event ) ){
    $event->load( 'eventQuestionUsers' );
  }

  return view( single_event, [
    'event' => $event
  ]);
}

But now I’m I would like the collection to split-up the eventQuestionUsers based on the user_id. So that it would look like this:
$event = [
  'name' => 'Blah blah',
  'date' => '2021-09-18 20:30:00'
  'eventQuestionUsers' => [
    15 => [ // 15 is a user_id
      $eventQuestionUser,
      $eventQuestionUser,
    ],
    16 => [ // 16 is a user_id
      $eventQuestionUser,
      $eventQuestionUser,
      $eventQuestionUser,
      $eventQuestionUser,
    ],
    18 => [ // 18 is a user_id
      $eventQuestionUser,
      $eventQuestionUser,
    ],
  ]

Solution attempt

Normally I would just make a public static helper-function, that takes $eventQuestionUsers and an input and returns what I want, by iterating over the whole this, like such:

public static function clusterEventQuestionUsersBasedOnUserId( $eventQuestionUsers ){
  $returned = [];
  foreach( $eventQuestionUsers as $eventQuestionUser ){
    $user_id = $eventQuestionUser->user_id;
    if( ! array_key_exists( $user_id, $returned ) ){
      $returned[ $user_id ] = [];
    }
    $returned[ $user_id ][] = $eventQuestionUser;
  }
  return $returned;
}

I wouldn’t use a Collection, since that is immutable, so adding entries like seen above usually is a bit of a pain.

What is ‘The Laravel Way’ of doing this? Or does it sound fine? It feels very ‘un-laravel’ like.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

By default, $event->eventQuestionUsers is a collection instance and this means you can use laravel collection methods directly on it and in this case, groupBy(). So

public function show( $event_id ){
  $user = Auth::user();
  $event = Event::where( [ 'id', '=', $event_id ] )->get();

  if( $user->can( 'manage', $event ) ){
    $event->load( 'eventQuestionUsers' );
    $event->eventQuestionUsers->groupBy('user_id');//the only new stuff
  }

  return view( single_event, [
    'event' => $event
  ]);
}

Method 2

Im unsure if i understood you correctly, but if you have the user_id in your relation, you can group by your lazy eager load like so

$event->load(['eventQuestionUsers' => function($query) {
    $query->groupBy('user_id');
}]);

Laravel Docs


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x