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

packy's avatar
Level 7

relationship groupBy in initial query

I am trying to groupBy a relationship in the initial query from my controller but not having such luck. For now I have a workout, but seems clunky:

public function menu(Location $location)
    {
        $location->entrees = $location->entrees->groupBy(function ($entree) {
            return $entree->course->name;
        });

        return view('food-order.menu', compact('location'));
    }

I thought it would look something like this

public function menu(Location $location)
    {
       $location->load(['entrees' => function ($q) {
            $q->groupBy(function ($entree) {
                return $entree->course->name;
            });
        }]);

        return view('food-order.menu', compact('location'));
    }

but get the error: stripos() expects parameter 1 to be string, object given. Is this way off target of how I should do this???

0 likes
12 replies
packy's avatar
Level 7

@snapey Whoops, fixed that mishap, groupBy is what I am looking for

Snapey's avatar

can you explain the relationships between the models?

packy's avatar
Level 7

They are as follows:

  • Locations belongsToMany Entrees
  • Entrees belongsToMany Locations
  • Entrees belongsTo Course
  • Course hasMany Entrees
packy's avatar
Level 7

@snapey the end result is I can loop through the "Groups" to show the course->name and then loop through the entrees that belong to that group AND that location like so (which works with my little hack):

@foreach ($location->entrees as $course => $entrees)

   <h2>{{$course}}</h2>

   <ul>
   @foreach ($entrees as $entree)

      <li>
         <p>{{ $entree->name }}</p>
         <p>{{ $entree->description }}</p>

      </li>

   @endforeach
   </ul>

@endforeach
Snapey's avatar

hmm, tricky

So you want to group entrees by the course?

Its hard to visualise, it seems a bit back to front. I would probably get location with eager load entrees.course and then group entrees by its course using a collection method.

    $entrees = $location->entrees()->with('course')->get();

    $grouped = $entrees->groupBy(function($entree){
                   return $entree->course->name;
               });

similar to yours, but loading the course.

packy's avatar
Level 7

@snapey yes, like you would see in a regular menu entrees grouped by a course like "appetizers". And a course really shouldn't belong to a location since really each location has all the same courses but not the same entrees under a course. I will give your solution a whirl

packy's avatar
Level 7

@snapey that seems to work as well. Is either option better performance wise I wonder? I am getting Allowed memory size of 134217728 bytes exhausted sometimes on load. Or maybe cache the results since items are rarely added or changed?

Snapey's avatar

this code should not do this, as your entrees are related to a single location?

do the query in tinker, and count the results to check its as expected

Snapey's avatar

personally, I would probably have course as an attribute of entree, not a separate model, bit I admit, I dont have the full knowledge of what you need to do.

packy's avatar
Level 7

@snapey Yes that was my initial thought but a course has a few things common to all entrees under it like "description" and "sides". But I might re tool it to make it work better

Snapey's avatar

The other thing I thought of was a courses relationship on Location which is a hasManyThough passing through entrees, you could then simply do $location->load('courses.entrees') and not bother with the grouping

Please or to participate in this conversation.