Laravel Relationship Union: One Relationship with two tables in a model

1.5k Views Asked by At

Lets supose this scenery:

We have 3 models -> User, Role and Permission.

Relationships

  • User has one to many relationship with Role.
  • Role has many to many relationship with Permission
  • User has many to many relationship with Permission.

The final purpose to the User -- Permisson relationships is to override the permission assigned to the user through his role. Just an exception for this User.

I am trying to to something like this:

public function permissions () {
    return $this->hasManyThrough('App\Permission', 'App\Role')->merge($this->permissionOverrides);
}

In this case when I try to eager load the model permissions Laravel throws an error 'cause permissions is not detected as a relationships.

In the other hand, what if we change User -- Role relationship to many to many?

Thanks a lot for your knowledge!

EDIT

Role Relationships

public function permissions() {
    return $this->belongsToMany('App\Permission')->withTimestamps();
}

Permission relationships

public function roles() {
    return $this->belongsToMany('App\Role')->withTimestamps();
}

User relationships

public function roles() {
    return $this->belongsToMany('App\Role')->withTimestamps();
}

public function permissionOverrides() {
    return $this->belongsToMany('App\Permission')->withTimestamps();
}

The question is how to make the permissions() relationship merging the role permissions and the user permissions.

BETTER EXPLANATION

Due to misunderstanding shown in comments I will try to exlain this better. I had set all the relations between App\User and App\Role; I also had set the the relationship between App\Role and App\Permission. I can do right now:

$user->role->permissions;

For obtaining this I have configured the pivot table permission_role which stores the relation.

Thats not the case. What I want is to add one more var to the equation. Now I want to have the ability to override the role permissions adding a relationship between App\User and App\Permission. I have the pivot table permission_user and the relation stablished:

public function permissionsOverride() {
    return $this->belongsToMany('App\Permission');
}

The REAL QUESTION is how to obtain all the permissions (both role permissions and overrided permissions in only ONE relationship). I mean merging both relationships.

Why I want to merge relationships? I could do a regular function to do this, but I would want to eager load this relation, Laravel way.

1

There are 1 best solutions below

5
rkj On

You can try like this, ManyToMany relation between User And Role, similarly ManyToMany relation between Role and Permission.

User Model

public function roles() {
    return $this->belongsToMany('App\Role', 'user_role')->withTimestamps();
}

public function permissions() {
    return $this->belongsToMany('App\Permission', 'permission_user')->withTimestamps();
}

Role Model

public function users() {
    return $this->belongsToMany('App\User', 'user_role')->withTimestamps();
}

public function permissions() {
    return $this->belongsToMany('App\Permission', 'permission_role')->withTimestamps();
}

Fetch Data

$user = User::with('permissions','roles','roles.permissions')->find(1);
$permissions = $user->permissions;
foreach($user->roles as $role){
   $permissions->merge($role->permissions); //merger collection
}

dd($permissions->all());

For details you can look https://laravel.com/docs/5.6/eloquent-relationships#many-to-many

And for Collection you can look this https://laravel.com/docs/5.6/collections#method-merge