Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

H4L1M's avatar
Level 1

Getting roles that has the same exact permissions

hello everyone, hope you are doing fine

in laravel 8 , am using the spatie package for managing roles and permissions , and it's doing great

how ever , i found that users can create roles with the same exact permissions (roles has many permissions) over and over again with different names

so my question is, how can i check if any existing role has the same exact given permissions by the user before creating a new one

0 likes
19 replies
H4L1M's avatar
Level 1

@Tray2 sorry i think I didn't mention that the package is using a polymorph relationship not one table

H4L1M's avatar
Level 1

@Tray2 yeah sure here are the default Permissions from my seeder

$DefaultPermissions = [
            'super admin',
            'profile.view', 'profile.edit',
            'role.view', 'role.edit', 'role.delete', 'role.create',
            'user.view', 'user.edit', 'user.delete', 'user.create', 'user.assign_role',
            'activityLog.view','activityLog.delete'
        ];

then the admin of the app is free to structure them into roles.

for example "Users Manager" role would have permissions to 'user.view', 'user.edit', 'user.delete', 'user.create', the problem is the admin can create another role "Dummy Role" with the same exact permissions

i solved it Using PHP by pulling all roles and i give em a check, but i would like to do it DB side

Sinnbeck's avatar

I think the only way will be to get every role and compare them one by one. This can be shortened a bit by checking if the permission count is the same (if it isnt, then it cannot be the same)

1 like
H4L1M's avatar
Level 1

@Sinnbeck

 $roles = Role::with('permissions')->get()->pluck('permissions')->map(function ($item, $key) {
            return $item->pluck('id');
        })->toArray();

this with return an array of roles with arrays containing ids for permissions

then i compare it to what the user posted like this

dd(in_array(array_values(Arr::sort($this->selectedPermissions)), $roles));

what do you think ? a bit big i know :p

H4L1M's avatar
Level 1

@Sinnbeck nope the first part of code is just to get all roles in the database with their permissions in an array like this

$db_roles = [
0=>[1,2],
1=>[2],
2=>[5,6]
];

then i check if the given array by user matches any of those sub-arrays with the php function in_array (it matches only if exact same array is founded)

in_array($ids_to_check, $db_roles);

it works ; Roles number in any application should not hit 3 digits any way .... but it's kind of Not LARAVALIAN solution yet :p

Sinnbeck's avatar

Think I found a way. $ids are the permission ids your are trying to check

$ids = [2,3,7];
$roles = Role::whereHas('permissions', function ($query) use ($ids) {
    $query->whereIn('id', $ids);
}, '=', count($ids))->get();

EDIT: might give issues if the role has extra permissions.. Damn

1 like
H4L1M's avatar
Level 1

@Sinnbeck yeah it returns roles that have either Permission "1" or "2" , i want them to be exactly "1" and "2"

Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

@merabetabdelhalim count them to check perhaps? This should work

$ids = [2,3,7];
$roles = Role::withCount('permissions') - >whereHas('permissions', function ($query) use ($ids) {
    $query->whereIn('id', $ids);
}, '=', count($ids))->get();
$final = $roles->filter(function ($item) use ($ids) {
    return $item->permissions_count === count($ids);
});
2 likes
H4L1M's avatar
Level 1

@Sinnbeck that does the trick thanks for burning some brain cells here , really appreciate it ! :D

oaaron's avatar

@Sinnbeck Was taking a look at this solution since I have a problem that has similar needs. Doesn't this solution fail when you have a similar set of permissions with the same count?

For example, the input [2,4,7] would fetch the same model as the input [2,3,7] since the whereIn will catch any permission with id 2 or 7 and the having / count will match since the array size is the same.

The whereIn does not ensure that ALL the ids are found, only that one of them is, or maybe I am missing something.

H4L1M's avatar
Level 1

@oaaron you are correct, i faced the same issue until i added

'=',count($value)

to whereHas so the code becomes

$similar_role = Role::withCount('permissions')
                ->whereHas('permissions', fn ($query) => $query->whereIn('id', $value),'=',count($value))
                ->having('permissions_count',count($value))
                ->get();

it works well , [2,4,7] input will not fetch the same model for [2,3,7] input now tell me if am doing something wrong ...

H4L1M's avatar
Level 1

hello again, if anyone is interested in a smaller solution a nice guy @erikn69 offered this (i think he's a part of the Spatie team)

$similar_role = Role::withCount('permissions')
            ->whereHas('permissions', fn ($query) => $query->whereIn('id', $selectedPermissions))
            ->having('permissions_count', count($selectedPermissions))->get();

it ll return just exactly the Similar roles (no need to check the count)

2 likes
Sinnbeck's avatar

@H4L1M ah I almost had it. Close to my initial idea, but clever with the having() check

1 like

Please or to participate in this conversation.