2
votes

I have got 3 tables: users; permissions; user_permissions.

My pivot table (user_permissions) has got 2 columns: user_id and permission_id.

How would I go about removing a permission for a user using the permission name, or an array of permissions?

So for example I could have:

array:1 [
  0 => "access_documentation"
]

Or I could have this:

array:4 [
  0 => "general_user"
  1 => "access_pagespeed"
  2 => "access_documentation"
  3 => "access_admin"
]

I have got a relationship for the users permissions, which returns the names.

public function permissions()
{
    return $this->belongsToMany(Permission::class, 'user_permissions');
}

What I have based on answers provided below:

public function save(User $user, Request $request)
{

    $params = Permission::query()->whereIn('name', $request->input('data'));

    if ($params->count() === 0) {
        return;
    }

    $params = $params->pluck('id')->toArray();

     $user->permissions()->detach();

    // $user->permissions()->attach(6);
    // $user->permissions

}

Edit

My permissions are split into categories, so when updating them I only send an array of permissions for that category, so doing $user->permissions()->detach() would detach unrelated permissions.

Is there a way I can say only detach or sync all with a certain category ID?

Example user_permissions

id      user_id      permission_id
1          32              1

Example permissions

id        name      category_id
1      edit_users        3

** Edit 2 **

$params returns selected permissions within that category, so based on the image below this will be an array [ 'general_user', 'access_pagespeed', 'access_admin' ]. If I was to click the fourth item in the list below then $params would then of course be [ 'general_user', 'access_pagespeed', 'access_admin', 'access_documentation' ].

enter image description here

2
Now this is interesting, will update you shortly. - Ray A
@RayA I could always pass in a single permission and if it was added or removed as I was doing before, as this would solve this issue with the categories? - Martyn Ball
this line $params = Permission::query()->whereIn('name', $request->input('data')); is returning all permission on specific category? - Ray A
@RayA That is returning all the selected permissions for that category, passed into the endpoint. - Martyn Ball
@RayA updated post with a screenshot of how I select the permissions. - Martyn Ball

2 Answers

1
votes

The laravel documentation states that you could use the detach method on the model to automatically remove the entries in the pivot table:

https://laravel.com/docs/5.8/eloquent-relationships#updating-many-to-many-relationships

So in your code you could always remove all permissions by detaching and then only readd the permissions from the array!

1
votes

There are couple of ways to do that: Option 1:

Using detach

Using this method will result in the user permission being reset, means, it will remove the user permissions from that table by setting the value of the permission to null.

More information can be obtained from: https://laravel.com/docs/5.8/eloquent-relationships#updating-many-to-many-relationships

Using sync:

Using this method will remove the permissions that are not part of the array you are sending, so you can use this only to keep the permissions you want instead of removing all permissions.

Suppose your user has the following permission IDs [1,2,3,4,5,6,7]

consider this line of code: $user->roles()->sync([1, 2, 3]);

This means the IDs of [1,2,3] will be kept in the pivot table while others will be removed.

More information can be obtained from: https://laravel.com/docs/5.8/eloquent-relationships#updating-many-to-many-relationships

I'll recommend you to use sync since you can keep only the permissions you need.


Update: Based on the updates you made to your question, I can suggest you do the following:

  • Add additional column to your user_permissions table and name it category_id, this category id must be the same category id of your permissions.

  • Use this code $user->permissions()->wherePivot('category_id', 3)->detach();, this will detach all permissions related to that category id.

I guess this would fix your problem.