Laravel:Has many through 在使用 whereHas 时不遵循条件

huangapple go评论67阅读模式
英文:

Laravel: Has many through not respecting whereHas

问题

I am trying to construct a hasManyThrough relationship in Laravel 10.

我正在尝试在 Laravel 10 中构建一个 hasManyThrough 关系。

I have 3 tables: users table (standard Laravel columns), client_assignments, and media_ad_plans.

我有3个表格:users 表格(标准 Laravel 列),client_assignmentsmedia_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.

用户可以在 client_assignments 表格中分配给多个客户。在 media_ad_plans 表格中,一项属于一个客户。

In my Users model I am defining the relationship like so:

在我的 Users 模型中,我像这样定义了关系:

public function adPlans(): HasManyThrough
{
return $this->hasManyThrough(
AdPlan::class,
ClientAssignment::class,
'user_id',
'client_id',
'id',
'client_id'
);
}

在我的 Users 模型中,我像这样定义了关系:

However, when doing something like:

但是,当进行如下操作时:

$users = User::with('adPlans.client')->whereHas('adPlans', function ($query) {
return $query->duringTodayUsing('material_deadline', false); // a custom scope
})->get();

$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.

返回了与用户关联的所有广告计划项,而不仅仅是与 whereHas 语句匹配的那些。我尝试在 whereHas 闭包中使用简单的查询,但它并没有改变输出 - 我仍然得到了用户的所有项目。我怀疑我的关系可能是错误的,或者我可能做了一些“不合法”的事情。我没有收到任何错误。

Client Assignments:

客户分配:

Ad Plan (useful fields per the question):

广告计划(根据问题的有用字段):

英文:

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:

Laravel:Has many through 在使用 whereHas 时不遵循条件

Ad Plan (useful fields per the question):

Laravel:Has many through 在使用 whereHas 时不遵循条件

答案1

得分: 3

->whereHas()在独立的->with()子句上没有效果。您的代码按预期工作;whereHas()根据'adPlans', function ($query) { ... })来过滤返回的User记录,但->with('adPlans.client')正确地返回每个User关联的所有adPlans记录。

您可以将逻辑复制到->with()子句上,如下所示:

$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();

或者使用Laravel的->withWhereHas()子句:

$users = User::withWhereHas('adPlans', function ($query) {
  return $query->with('client')->duringTodayUsing('material_deadline', false);
})->get();

文档链接:

https://laravel.com/docs/10.x/eloquent-relationships#constraining-eager-loads-with-relationship-existence

英文:

->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:

https://laravel.com/docs/10.x/eloquent-relationships#constraining-eager-loads-with-relationship-existence

huangapple
  • 本文由 发表于 2023年6月29日 11:28:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76577895.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定