Model: many-to-many relationship
I have 3 tables. Lets say Person that has a many-to-many relationship with Department that has a many-to-many relationship with Function.
So, I want to get the functions for every department that a person belongs.
I am a bit confused how I can achieve that with Eloquent and how I should create my models.
Thank you in advance!
@RachidLaasri doesn't work with many to many.
@ounos There is no way to do it easily with eloquent. Except a many to many between users and functions.
To get a Person's departments, and each of those departments' functions:
Person::all()->with('department.function')->get()
This assumes you have the necessary relationships 'department' set up in the Person model, and a 'function' relationship in the Department model.
@DMA I think he wants something like $person->functions to loop through for example.
@pmall exactly! I need all functions, for every department that a person belongs to.
As @pmall mentioned, create a direct relationship between User model and functions.
@RachidLaasri this is not what I need. Read my last comment again please.
There is a little bit of my eloquent trickery that easily does the job:
// Assuming you want all Functions of User id = 1
$user = User::find(1);
$user->load(['departments.functions' => function ($q) use ( &$functions ) {
$functions = $q->get()->unique();
});
// or
// User::with(['departments.functions' => function ($q) use ( &$functions ) {
// $functions = $q->get()->unique();
// })->find(1);
// now
$functions; // collection of all functions of the user through his departments
Notice & - $functions is passed by reference and the query in the closure is executed instantly with get()
Doing so doesn't affect lazy/eager loading in any way - it runs additional query, but keeps the rresult before it's matched to the relation parents (departments in this case). Downside is this additional query, but it's really convenient to do it with this one-liner instead of loops. Additionally it will work for any level of nesting, ie. even if you have user >< department >< function >< somethingelse >< yetanotherlevel - you can get yetanotherlevel exactly the same - imagine how many foreach loops you would need otherwise...
@ounos I think @DMA was right you need to use . while skipping from one segment deeper in relationships. This way you can get:
foreach($departments as $department)
{
foreach($department->users as $user)
{
foreach($user->functions as $function)
{
//
}
}
}
I also use a function like that: Here is the query:
Category::with(['subCategories.products'])->get()->toArray();
Here is my blade:
@foreach($categories as $category)
@foreach($category['sub_categories'] as $subCategory)
<div class="nav-content-col">
<h3>{{ $subCategory['name'] }}</h3>
<ul>
@foreach($subCategory['products'] as $product)
<li>
{!! link_to_route('product', $product['name'], [$product['slug']]) !!}
</li>
@endforeach
</ul>
</div>
@endforeach
@endforeach
Please or to participate in this conversation.