staudenmeir / eloquent-has-many-deep

Laravel Eloquent HasManyThrough relationships with unlimited levels
MIT License
2.67k stars 157 forks source link

User has many deep User through 2 many-to-many relationships. #80

Closed buglinjo closed 4 years ago

buglinjo commented 4 years ago

I'm having trouble writing hasManyDeep relationship.

I want to create a relationship which will return User's related Users through many to many relationship with Branch.

User -> branches_users -> Branch -> branches_users -> User

My current code:

return $this
    ->hasManyDeep(User::class, ['branches_users', Branch::class, 'branches_users'])
    ->select('users.*');

It is generating incorrect SQL. Generated SQL:

select `users`.*
from `users`
         inner join `branches_users` on `branches_users`.`user_id` = `users`.`id`
         inner join `branches` on `branches`.`id` = `branches_users`.`branch_id`
         inner join `branches_users` on `branches_users`.`branch_id` = `branches`.`id`
where `branches_users`.`user_id` = 1

It should generate something like this:

select `u`.*
from `users`
         inner join `branches_users` as bu1 on bu1.`user_id` = `users`.`id`
         inner join `branches` on `branches`.`id` = bu1.`branch_id`
         inner join `branches_users` as bu2 on bu2.`branch_id` = `branches`.`id`
         inner join users as u on bu2.user_id = u.id
where users.id = 1
staudenmeir commented 4 years ago

It's possible with a pivot model and a table alias:

class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function users()
    {
        return $this->hasManyDeep(
            User::class,
            [BranchUserPivot::class, Branch::class, BranchUserPivot::class.' as alias']
        )->select('users.*');
    }
}

class BranchUserPivot extends \Illuminate\Database\Eloquent\Relations\Pivot
{
    use \Staudenmeir\EloquentHasManyDeep\HasTableAlias;

    protected $table = 'branches_users';
}
buglinjo commented 4 years ago

Worked perfectly, thank you!