I am trying to construct a hasManyThrough
relationship in Laravel 10.
I have 3 tables: users
table (standard Laravel columns), client_assignments
, and media_ad_plans
A user can be assigned to multiple clients in the client_assignments
table. In the media_ad_plans
table an entry belongs to one client.
In my Users
model I am defining the relationship like so:
public function adPlans(): HasManyThrough
{
return $this->hasManyThrough(
AdPlan::class,
ClientAssignment::class,
'user_id',
'client_id',
'id',
'client_id'
);
}
However, when doing something like:
$users = User::with('adPlans.client')->whereHas('adPlans', function ($query) {
return $query->duringTodayUsing('material_deadline', false); // a custom scope
})->get();
All of the ad plan items associated with a user are returned, not just the one’s that match the whereHas
statement. I’ve tried a simple query within the whereHas
closure but it does not change the output – I still get all items for the user. I suspect my relationship is malformed or perhaps I am doing something "illegal." I am not getting any errors.
Client Assignments:
Ad Plan (useful fields per the question):
>Solution :
->whereHas()
has no effect on a separate ->with()
clause. Your code is working exactly as expected; whereHas()
is filtering which User
records are returned, based on 'adPlans', function ($query) { ... })
, but ->with('adPlans.client')
is correctly returning ALL of each User
‘s associated adPlans
Records.
You either need to duplicate your logic onto your ->with()
clause, like:
$users = User::with(['adPlans' => function ($query) {
return $query->with('client')->duringTodayUsing('material_deadline', false);
}])->whereHas('adPlans', function ($query) {
return $query->duringTodayUsing('material_deadline', false);
})->get();
Or use Laravel’s ->withWhereHas()
Clause:
$users = User::withWhereHas('adPlans', function ($query) {
return $query->with('client')->duringTodayUsing('material_deadline', false);
})->get();
Documentation: