How can I build a query in my controller action that indexes parent models, with parent-specific children nested using foreach loops?

Viewed 28

I'm currently trying to create an index of cards depicting rooms, with their associated desks indexed within them, using nested foreach loops within the view:

<div class="grid grid-cols-1 gap-3 ">
                    @foreach ($rooms as $room)
                        <div class="bg-white text-center h-auto">
                            {{ $room->name }}
                            <div class="m-3">
                                <div class="lg:grid lg:grid-cols-6 gap-3">
                                    @foreach ($desks as $desk)
                                        <div class="bg-red-200 text-center h-10">
                                            Desk {{ $desk->id }}
                                        </div>
                                    @endforeach
                                </div>
                            </div>
                        </div>
                    @endforeach
                </div>

The Room controller index action currently looks like this:

class RoomController extends Controller
{
    public function index()
        {
    
            return view('index', [
                'rooms' => Room::all(), 
                'desks' => Desk::all()
            ]);
        }
}

I'm aware that Desk::all() is indexing all desks for all rooms. Instead, I need to build a query that indexes desks belonging only to each room. My model relationships are defined as:

Room hasMany desks

Desk belongsTo room

Any help would be much appreciated, thanks.

2 Answers

instant doing like rooms::all and desk::all use can simply run an eloquent query like:-

room::with("desks")->get();

note :-you need to make a relation in your room model with name "desks" like this :-

public function desks(){
    return $this->hasMany(desk::class);
} 

and your foreign key name must be like model name +_id

Managed to solve this. Desk::all() worked as I wanted to make all desks available at controller level. Instead I added a where clause to the nested foreach loop to filter by room_id:

<div class="grid grid-cols-1 gap-3 ">
                    @foreach ($rooms as $room)
                        <div class="bg-white text-center h-auto">
                            {{ $room->name }}
                            <div class="m-3">
                                <div class="lg:grid lg:grid-cols-6 gap-3">
                                    @foreach ($desks->where('room_id', $room->id) as $desk)
                                        <div class="bg-red-200 text-center h-10">
                                            Desk {{ $desk->id }}
                                        </div>
                                    @endforeach
                                </div>
                            </div>
                        </div>
Related