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

Martin20's avatar

I want to display all roles who this user {id} don't have.

i have 3 tables,

table user: 
id, 
userame
table roles:
id,
name,
table user_has_roles:
 id ,
 role_id, 
 user_id
0 likes
20 replies
Martin20's avatar

i have this error

BadMethodCallException
Call to undefined method Modules\UserPermission\Models\Role::users(

yes i use spatie package

MichalOravec's avatar

If you use that package then your table structure is wrong. Behind the scene they use polymorphic relationships.

1 like
Martin20's avatar

please can you help me how can i do in that package, i just need a query or tutorial

Martin20's avatar

I want to display all roles who this user {id} don't have. , i try that in blade but

 @foreach($roles as $role)
       @foreach($user->modelHasRoles as $user->modelHasRole)
               @if($user->modelHasRole->role_id != $role->id)
                   <option value="{{$role->id}}">{{$role->name}}</option>
               @else
               @endif
      @endforeach
@endforeach
                                          	

if this user have 1 role this work https://prnt.sc/vwcol7 , but if this user have multiple role i get this https://prnt.sc/vwcpm5 roles who this user have are display and role who this user don't have are doubled , so i get all roles and roles who this user don't have but i want to display only the roles who this users don't have

MichalOravec's avatar

Model Role has to have a users relationship then this will work

$roles = Role::whereDoesntHave('users', function ($query) use ($userId) {
    $query->where('users.id', $userId);
})->get();

I don't know why you have different setup for models a relationships, maybe you use older version.

1 like
Martin20's avatar

can you give me relationships I need to do please

Martin20's avatar

in Role Model

public function modelHasRoles()
    {
        return $this->hasMany('Modules\UserPermission\Models\ModelHasRoles', 'model_id', 'id');
    }

in ModelHasRolesModel

 public function users()
    {
        return $this->hasMany('Modules\UserPermission\Models\User', 'user_id', 'model_id');
    }

I have that but don't know how to get the user relationship here ''modelHasRoles.users''

$roles = Role::whereDoesntHave('modelHasRoles.users', function ($query) use ($userId) {
            $query->where('modelHasRoles.users.user_id', $userId);
        })->get();
Martin20's avatar

how can i to add users relationship please can you give me 1 example ?

GeordieJackson's avatar

A simple way to do this is to extract the User's Roles from all Roles before passing the data to the blade for display.

i.e. Get a collection of all roles, a collection the user's roles and use $collection->diff() to subtract the user's roles out.

$allRoles = Role::all();
$userRoles = User::find($id)->roles;

$unassignedRoles = $allRoles->diff($userRoles);

Then pass $unassignedRoles into your blade. You'd have to adapt the code to suit the way you've done it, but that's one way. It will at least give you a workable solution until you sort out your Role/User relationships.

1 like
Martin20's avatar

i can't find roles

$userRoles = User::find($id)->roles;
jlrdw's avatar

@martin20 it is example, you use role_id. So get all role_id assigned to user.

Next you have all roles, then do diff. Just think through the steps.

user 5 has roles 1,3,4,5

all roles 1,2,3,4,5

Then do diff. user 5 is missing role 2. You could also loop, but up to you.

Look at this array_diff() example:

https://www.w3schools.com/php/func_array_diff.asp

1 like
Martin20's avatar

i try that but i get all roles, don't know where is the problem

$user_id=1;
$allRoles = Role::all('id');
$userRoles = ModelHasRoles::where('model_id',$user_id)->get('role_id');
$roles = $allRoles->diff($userRoles);
 dd($roles);
jlrdw's avatar
jlrdw
Best Answer
Level 75

@martin20 This works, tested:

        $id = 1;   ///   just example, get from input

        $userRoles = DB::table('user_has_roles')
                ->select('role_id')
                ->where('user_id', '=', $id)  // $id is correctly passed id of user.
                ->get();
        $ur = [];
        foreach ($userRoles as $v) {
            $ur[] = $v->role_id;
        }


        $allroles = DB::table('roles')
                ->selectRaw('id as role_id')
                ->get();
        $ar = [];
        foreach ($allroles as $b) {
            $ar[] = $b->role_id;
        }

        $diff = array_diff($ar, $ur);

        dd($diff);

Where roles are

  • 1, 2, 3

The user has roles:

  • 2, 3

The difference shows:

array:1 [▼
  0 => 1         ////   does not have this role
]

Which is correct, in test I only assigned role 2 and 3 to user, so in above user does not have role 1.

I just tested using query builder so I wouldn't have to setup models also.

This works 100% You have to remember, these things can take a little trial and error.

2 likes
Martin20's avatar

This works very well i have and one question: Is that ok in big projects?

Martin20's avatar

how can i display the id and the name of role in blade from this array ?

jlrdw's avatar

Use eloquent, I just use Query Builder for testing. Don't forget eloquent is already arrayable.

And in real project I would probably show more fields. But the best of luck with your project.

I did it that way because you stated there was some things you could not change.

2 likes

Please or to participate in this conversation.