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

eleven0's avatar

Nested Foreach (Eager Loading) - Displaying Retrieved Data

I have got three models

Contacts Model ContactRoles Model Project Model

Set-up I have contacts can belong to multiple projects. (Many to Many) each project has its own contact roles created by user. (One to Many Roles are specific to projects) Within selected project, a contact can be assigned to multiple roles (Many to many). I am currently building my blade view files and have an issue with loading the data with foreach loop and an if statement.

How I retrieve data in controller;

 $project = Project::with('contacts.contactrole','companies.companyrole')->findOrFail($projectid);

Question 1:

            @foreach ($project->contacts as $contact)
                @foreach ($contact->contactrole as $role)
                    @if ($role->group == 'consultant')
                    <li> {{$contact->firstname}} - {{$role->label}} </li>
                    @endif
                @endforeach
            @endforeach

Above code works, when a contact has multiple roles, since i iterate through role, listing is repeating it self. How can i constrain inner foreach so that I can iterate through contacts only with "group" condition?

0 likes
4 replies
lostdreamer_nl's avatar

you could do a where on the Collection object:

            @foreach ($project->contacts as $contact)
                @foreach ($contact->contactrole->where('group', 'consultant') as $role)
                    <li> {{$contact->firstname}} - {{$role->label}} </li>
                @endforeach
            @endforeach

It wont be doing extra queries because it's already a collection object.

eleven0's avatar

it has no affect. It is still repeating itself as many as total number of contact's role. If one contact is both a consultant and a say a project manager - listing would repeat it self a second time, and it goes on like this...

lostdreamer_nl's avatar
Level 53

I dont get this part: "(One to Many Roles are specific to projects)"

Does the contactrole have a project_id ?

If so, you could do it like this:

@foreach ($project->contacts as $contact)
  @foreach ($contact->contactrole->where('group', 'consultant')->where('project_id', $project->id) as $role)
    <li> {{$contact->firstname}} - {{$role->label}} </li>
  @endforeach
@endforeach

eleven0's avatar

@lostdreamer_nl I ended up doing a version of what you suggested and finally got it working. I created additional columns in my contactrole pivot table, and code became following.


@foreach ($project->contacts->where('pivot.role_group','consultant') as $contact)
                        <li> {{$contact->firstname}} -{{$contact->pivot->role_label}}
                        </li>
                        @endforeach ```

Please or to participate in this conversation.