Laravel Nested Relationships

Laravel nested relationships

return Event::with('city.companies.persons')->get();

If you only want to select certain fields from the persons table, use this:

return Event::with(['city.companies.persons' => function ($query) {
$query->select('id', '...');
}])->get();

Query Laravel nested relationship [Laravel 6.x]

Try this for the categories query:

$categories = Category::with(['events' => function ($query) use ($region) {
$query->where('region_id', $region->id);
}])->take(5)->get();

Check the documentation on restraining eager loads

Laravel eloquent with() nested relationship fields in parent unnested

i found 2 solutions to my issue.

the first solution is accepting relations are nested and making sure they return default fields with the "withDefault()" method. which would look like:

$rows = ProjectLogin::
with([
'User' => function($query) {
$query->select('PRIVATE','naam')
->withDefault(['PRIVATE' => '','naam' => '']);
},
'Project' => function($query) {
$query->select('PRIVATE','naam')
->withDefault(['PRIVATE' => '','naam' => '']);
},
'Queue' => function($query) {
$query->select('PRIVATE','queue_naam')
->withDefault(['PRIVATE' => '','queue_naam' => '']);
},
'AgentStatus' => function($query) {
$query->select('PRIVATE','status','status_colour')
->withDefault(['PRIVATE' => '','status' => '','status_colour' => '']);
},
]
)->get();

the other solution is if nested array are not a option is using "map()" which would look like:

$rows = ProjectLogin::with(
'User:PRIVATE,naam',
'Project:PRIVATE,naam',
'Queue:PRIVATE,queue_naam',
'AgentStatus:PRIVATE,status,status_colour'
)
->get()
->map(function($item) {
$item = $item->toArray();
return [
'PRIVATE' => $item['PRIVATE'],
'PRIVATE' => $item['PRIVATE'],
'PRIVATE' => $item['PRIVATE'],
'PRIVATE' => $item['PRIVATE'],
'user_name' => @$item['user']['naam'],
'project_name' => @$item['project']['naam'],
'queue_name' => @$item['queue']['queue_naam'],
'status' => @$item['agent_status']['status'],
'PRIVATE' => $item['PRIVATE'],
'status_colour' => @$item['agent_status']['status_colour'],
];
});

the $item = $item->toArray(); is important, otherwise it will create new queries that make n+1 obsolete.

Nested relation whereHas in laravel

Okay for a while I was think about my problem finally I got the answer. Okay for sharing to everyone I will explain a little bit for the answer.

So the query what I wrote on the controller, I change into this :

$getData = StockIn::with(['type_of_items' => function ($type_of_item) {
$type_of_item->select('id_type_item', 'type_id_item', 'code_type_of_item', 'type_of_item')
->with(['items' => function ($item) {
$item->select('id_item', 'item_id_common_unit', 'name_item')
->with(['common_units' => function ($common_unit) {
$common_unit->select('id_common_unit', 'name_unit');
}]);
}]);
}])
->with(['stock_out_left_join' => function ($stock_out_left_join) {
$stock_out_left_join->select('id_stock_out', 'stock_out_id_stock_in');
}])
->whereHas('type_of_items', function ($type_of_items_search) use ($search) {
$type_of_items_search->where('code_type_of_item', 'like', "%{$search}%")
->orWhere('type_of_item', 'like', "%{$search}%");
})
->orWhereHas('type_of_items.items', function ($items_search) use ($search) {
$items_search->where('name_item', 'like', "%{$search}%");
})
->orWhereHas('type_of_items.items.common_units', function ($common_units_search) use ($search) {
$common_units_search->where('name_unit', 'like', "%{$search}%");
})
->orWhere('created_by', 'like', "%{$search}%")
->orWhere('edited_by', 'like', "%{$search}%")
->get()
->toArray();

As you can see my new query has a new parameter in every with function and I was naming all the parameter with different name, and not like first name before query, so the problem is the ambiguous paramater in every single with function because this query based on nested relation so I must make the parameter name different each other. Or you want make them into split one by one and not using the nested with function you can use this query too, I put on this bellow :

$getData = StockIn::with(['type_of_items' => function ($query) {
$query->select('id_type_item', 'type_id_item', 'code_type_of_item', 'type_of_item');
}])
->with(['type_of_items.items' => function ($query) {
$query->select('id_item', 'item_id_common_unit', 'name_item');
}])
->with(['type_of_items.items.common_units' => function ($query) {
$query->select('id_common_unit', 'name_unit');
}])
->with(['stock_out_left_join' => function ($query) {
$query->select('id_stock_out', 'stock_out_id_stock_in');
}])
->whereHas('type_of_items', function ($query) use ($search) {
$query->where('code_type_of_item', 'like', "%{$search}%")
->orWhere('type_of_item', 'like', "%{$search}%");
})
->orWhereHas('type_of_items.items', function ($query) use ($search) {
$query->where('name_item', 'like', "%{$search}%");
})
->orWhereHas('type_of_items.items.common_units', function ($query) use ($search) {
$query->where('name_unit', 'like', "%{$search}%");
})
->orWhere('created_by', 'like', "%{$search}%")
->orWhere('edited_by', 'like', "%{$search}%")
->get()
->toArray();

I already tried that query and it's work too (with the same name parameter in every single with function).

Laravel Eloquent - How to get nested relationship

A shortcut that I can think of is making a many to many relationship between teachers and objectives, using ratings as the pivot table. So the distance between teachers and competencies is a bit shorter.

class Teacher
{
public function objectives()
{
return $this->belongsToMany(Objective::class, 'ratings');
}
}

Later on, you can get all the data by saying:

    $teachers = Teacher::with('objectives.competency', 'objectives.ratings')->get();

And from the view you can do something like:

@foreach($teachers as $teacher)
<h1>{{$teacher->first_name}} {{$teacher->last_name}}</h1>
@foreach($teacher->objectives->groupBy('competency_id') as $groupedObjectives)
<h2>Competency: {{$groupedObjecttives->first()->competency->title}}</h2>
@foreach($groupedObjectives as $objective)
<p>{{$objective->title}}: {{$objective->ratings->implode('score', ', ')}}</p>
@endforeach
@endforeach
@endforeach

Nested relationship access with Laravel 8

I think you have failed to improvise here.
Did you try this?

Assuming what you need is the car plate number,

You could,

$details = BookingDetails:with('route')->get();

in the blade,

$details->route->car->plate_number

Check this and reply. And don't forget to mark as answer if found useful.

Laravel 8 nested Model Relationships

Your main issue is that you need to nest the query.

  • I will first adding the relationships to your models according to your schema.

  • Then, I will add the base query for the nesting if I understood what you're trying to achieve correctly.

Models

Theme.php


public function subStatements()
{
return $this->hasMany(Statement::class); // 1-N
}

public function statements()
{
return $this->belongsToMany(Statement::class); // N-N
}

public function resources
{
return $this->belongsToMany(Resource::class); // N-N
}

Statement.php


public function theme()
{
return $this->belongsTo(Theme::class); // 1-N
}

public function themes()
{
return $this->belongsToMany(Theme::class); // N-N
}

public function resources
{
return $this->belongsToMany(Resource::class); // N-N
}

Resource.php


public function themes()
{
return $this->belongsToMany(Theme::class); // N-N
}

public function statements()
{
return $this->belongsToMany(Statement::class); // N-N
}

Query


$themes = Theme::query()
->where('category_id', $category_id)
->with([
'subStatements' => fn ($query) => $query->with('resources')
])
->get();

Complex eloquent nested relationship queries with Laravel

I suggest group with where the query before use orWhere, for prevent not filter the previous wheres, is like add parenthesis enclosing the inner conditions.

CourseEnrollment::whereIn('domain_id', $domain_ids)
->whereHas('member', function ($query) use ($filterUser) {
if ($filterUser === 'true') {
$query->where('email', 'NOT LIKE', '%@gmail.com%');
$query->where('email', 'NOT LIKE', '%@yahoo.com%');
$query->where('email', 'NOT LIKE', '%@boss.com%');
$query->where('email', 'NOT LIKE', '%@test.com%');
}

$query
->where(function ($sub) {
$sub->where('is_mentor', 1);
$sub->orWhere('privileges', '!=', 0);
});
})
->get();


Related Topics



Leave a reply



Submit