简体   繁体   中英

Eloquent multiple nested relations with constraint

Trying to get data from multiple nested relationship with a where constraint:

Model User:

    <?php

    use Illuminate\Auth\UserInterface;
    use Illuminate\Auth\Reminders\RemindableInterface;
    use Illuminate\Database\Eloquent\SoftDeletingTrait;
    use Zizaco\Entrust\HasRole;

  class User extends BaseModel implements UserInterface, RemindableInterface {
  use HasRole;

protected $fillable = array('username', 'password');
/**
 * The database table used by the model.
 *
 * @var string
 */
protected $table = 'users';

/**
 * The attributes excluded from the model's JSON form.
 *
 * @var array
 */
protected $hidden = array('password');
protected $dates = ['deleted_at'];
protected $softDelete = true;  

 public function editor()
{
    return $this->hasOne('User_Editor', 'user_id');
}
?>

Model User_Editor:

   <?php

   class User_Editor extends BaseModel {
/**
 * The database table used by the model.
 *
 * @var string
 */
protected $table = 'users_editors';

/**
 * The attributes excluded from the model's JSON form.
 *
 * @var array
 */
protected $hidden = array();

/**
 * Defiens the column names of fillable columns.
 *
 * @var array
 */
protected $fillable = array();

/**
 * Relationships
 */
public function credentials()
{
    return $this->hasMany('User_Editor_Credential', 'user_editor_id');
}

public function specialties()
{
    return $this->hasMany('User_Editor_Specialty', 'user_editor_id');
}
?> 

Model User_Editor_Credentials:

    <?php

 class User_Editor_Credential extends BaseModel {
/**
 * The database table used by the model.
 *
 * @var string
 */
protected $table = 'users_editors_credentials';

/**
 * The attributes excluded from the model's JSON form.
 *
 * @var array
 */
protected $hidden = array();

/**
 * Defiens the column names of fillable columns.
 *
 * @var array
 */
protected $fillable = array();
 }

Model User_Editor_Specialties:

    <?php

     class User_Editor_Specialty extends BaseModel {
/**
 * The database table used by the model.
 *
 * @var string
 */
protected $table = 'users_editors_specialties';

/**
 * The attributes excluded from the model's JSON form.
 *
 * @var array
 */
protected $hidden = array();

/**
 * Defiens the column names of fillable columns.
 *
 * @var array
 */
protected $fillable = array();
 }

Return

select * from User, User_Editor, User_Editor_Credentials, User_Editor_Specialty where User_Editor_Specialty.specialty In (array).

So far I've tried,

    $this->data['editors'] = User::with(['editor.credentials.specialties' => function($q) use($data){
            $q->whereIn('specialty',$data);
        }])
        ->get();

But this throws an error call to undefined method specialties. Please guide, thanks.

To those who might have suffered for long trying to find a way to work around nested relationships, and also, if you are writing a join condition with whereIn (which throws call to undefined method because of a bug in the Laravel), Please find below ans,

    $editors = User::with(['editor.credentials','editor.specialties']);
    $this->data['editors'] = $editors->whereHas('editor', function($q) use ($a_data){
       $q->whereHas('specialties',function($sq) use($a_data){
            $sq->whereIn('specialty',$a_data);
       });
    })->get();

Update: the PR has been just merged to 4.2, so now it's possible to use dot nested notation in has methods ( ->has('relation1.relation2) ->whereHas('relation1.relation2, .. )

Your dot notated relations must be logically chained:

`with(['editor.credentials', ' editor.specialties' => function ....

You tried to search for the specialties relation on the User_Editor_Credential model.


According to the comments:

User::with(['editor.credentials','editor.specialties'])
    ->whereHas('editor' => function($q) use ($data){
       $q->whereHas('specialties' => function($q) use ($data){
          $q->whereIn('specialty',$data);
       });
    })->get();

or if you use my PR https://github.com/laravel/framework/pull/4954

User::with(['editor.credentials','editor.specialties'])
    ->whereHas('editor.specialties' => function($q) use ($data){
        $q->whereIn('specialty',$data);
    })->get();

It will return all the users that have related editor.specialties matching whereIn , with related editor and all its related credentials and specialties (the latter won't be filtered)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM