1

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.

Javier Torron Diaz
  • 347
  • 1
  • 4
  • 25
  • For user/role you could setup a pivot table called role_user which many users can have many roles, and many roles can have many users. Since you're getting the permissions not detected as a relationship, have you setup the relationship between `App/Role` and `App/Permission`? –  Jul 03 '18 at 08:25
  • That relationship is set in the Role model. The question comes when I try to merge both. I have tried this what you're saying. I will put the relationship stablished on my question. – Javier Torron Diaz Jul 03 '18 at 08:36
  • Wouldn't it be best if you create a many to many between app/role and app permission, setup a pivot table called permission_role, then setup another pivot table between user/role called role_user. Since users can belong to roles and roles have permissions. Then you can call something like `$user->roles()->permissions` to get a collection of permissions? –  Jul 03 '18 at 08:53
  • 1
    [Here is a pretty good article that explains pivot tables and many to many relationships](https://laraveldaily.com/pivot-tables-and-many-to-many-relationships/) –  Jul 03 '18 at 08:58
  • I supose I have not explained properly. The relationships between roles and permissions are set. That is not the case. I want to merge 2 relationships.... – Javier Torron Diaz Jul 03 '18 at 10:31
  • 1
    https://stackoverflow.com/q/24184069/5283119 give this a read. –  Jul 03 '18 at 10:33
  • Yes, I had read that question before posting mine. That guided me, but as you can see, in it is defining an accesor, I had tried merging the relationships, but it dont works. I wanna write it as "Laravel way", I mean, as a relationship I could eager load on demand, even use Query Builder in this merged relationship. – Javier Torron Diaz Jul 03 '18 at 10:41
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/174244/discussion-between-mike-rodham-and-lordvermiis). –  Jul 03 '18 at 10:45

1 Answers1

1

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

rkj
  • 8,067
  • 2
  • 27
  • 33