【问题标题】:Filter model, then join with many-to-many relation过滤模型,然后加入多对多关系
【发布时间】:2014-12-31 09:18:37
【问题描述】:

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

  1. 获取指定列值的所有用户,例如:SELECT * FROM users WHERE business_unit = Finance;
  2. 获取关联的trainings,其中透视列值为is_speaker = true

换句话说,访问者搜索其(第一位)发言人属于指定业务部门的所有培训。

这是我迄今为止尝试过的:

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

【问题讨论】:

    标签: laravel filter many-to-many eloquent


    【解决方案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;
    });
    

    【讨论】:

    • 这不是我所需要的,但你帮助我进步了。您的查询似乎返回了属于指定业务部门并且也是发言人的所有用户。我需要退回演讲者属于业务部门的培训。我会将我的编辑添加到您的答案中。
    • 现在,我添加了似乎对我有用的东西,但并不完全。该代码返回指定业务部门中至少有一位发言人的所有培训。每次培训我只需要找一位演讲者(最好是->first())并检查他们的业务部门。能做到吗?
    • 如果在whereHas 闭包中添加$q->take(1) 会怎样?
    • 它似乎没有改变任何东西。
    • 你的意思是当你做$training->users时你只想得到一个?还是我理解错了?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    相关资源
    最近更新 更多