过滤模型,然后加入多对多关系

时间:2014-12-31 09:18:37

标签: laravel filter many-to-many eloquent

我有两个模型,UserTraining。它们与is_speakeris_creator等其他数据透视字段具有多对多关系。我想:

  1. 获取具有指定列值的所有用户,例如:SELECT * FROM users WHERE business_unit = Finance;
  2. 获取枢轴列值为training的相关is_speaker = true;
  3. 换句话说,访问者搜索其(第一)发言人属于指定业务单位的所有培训。

    这是我到目前为止所尝试的:

    $bu_users = $this->user->where( 'business_unit', $business_unit )->get();
    $speakerTrainings = $bu_users->trainings()->wherePivot( 'is_speaker', true )->get();
    dd( $speakerTrainings );
    // Returns: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'pivot' in 'where clause' (SQL: select * from `trainings` where (select count(*) from `users` inner join `training_user` on `users`.`id` = `training_user`.`user_id` where `training_user`.`training_id` = `trainings`.`id` and `business_unit` = Finance and `users`.`is_active` = 1) >= 1 and `pivot` = is_speaker)
    

    $bu_trainings = $this->training->with( 'users' )
        ->where( 'business_unit', '=', $business_unit )
        ->wherePivot( 'is_speaker', true)
        ->get();
    dd( $bu_trainings );
    // Returns: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'business_unit' in 'where clause' (SQL: select * from `trainings` where `business_unit` = Finance and `pivot` = is_speaker)
    

1 个答案:

答案 0 :(得分:1)

你关闭了。现在我们需要混合您的两个查询并添加一些whereHas

试试这个(此代码返回属于指定业务单位的所有用户,并且也是任何培训的发言人):

$users = $this->user
         ->whereHas('trainings', function($q){
             $q->where('training_user.is_speaker', true);
         })
         ->where('business_unit', $business_unit)
         ->get();

此代码将返回所有至少有一位来自指定业务单位的发言人的培训:

$trainings = $this->training->whereHas( 'users', function( $q )
{
    $business_unit  = Input::get( 'bu' );
    $q->where( 'training_user.is_speaker', true );
    $q->where( 'business_unit', $business_unit );
})->get;

修改

我知道这不是理想的,但这是我能想到的唯一有效的方法

首先,为了便于使用,请定义speakers关系

public function speakers(){
    return $this->belongsToMany('User')->wherePivot('is_speaker', true);
}

然后,首先,急切加载所有发言者,然后过滤(编辑)训练:

$business_unit = Input::get('bu');
$trainings = $this->training->has('speakers')->with('speakers')->get();
$trainings = $trainings->filter(function($training) use ($business_unit){
    return $training->speakers->sortBy('training_user.id')->first()->business_unit == $business_unit;
});