3
votes

From my controller I would like to select all of the users that have the role "client".

I have a User model and a Role model. A role belongs to many users and a user belongs to many roles.

I've established my models and have some helper functions at the model instance level for fetching roles and users

Here are the User and Role database models:

app/User.php

class User extends Authenticatable
{
    use Notifiable;

    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];

    // User belongs to many roles
    public function roles()
    {
        return $this->belongsToMany('App\Role')->withTimestamps();
    }

    // whitelist specific roles
    // reject if user does not have given roles
    public function authorizeRoles($roles)
    {
        if ($this->hasAnyRole($roles)) {
            return true;
        }

        abort(401, 'This action is unauthorized.');
    }

    // Check if a user has a role
    public function hasRole($role)
    {
      if ($this->roles()->where('name', $role)->first())
      {
        return true;
      }

      return false;
    }

    // Pass in string or array to check if the user has a role
    public function hasAnyRole($roles)
    {
      if (is_array($roles)) {
        foreach ($roles as $role) {
          if ($this->hasRole($role)) {
            return true;
          }
        }
      } else {
        if ($this->hasRole($roles)) {
          return true;
        }
      }
      return false;
    }
}

app/Role.php:

class Role extends Model
{
    public function users()
    {
        return $this->belongsToMany('App\User')->withTimestamps();
    }
}

I have migrations for a create_users_table, create_roles_table and a pivot table for create_role_user_table. Each role has an id, name and description. Each user has an id, name, email and password.

I would like to filter by all users that have the role called "client".

In my controller method I try to call roles but it does not work because it is an instance method:

// Display admin dashboard
public function admin(Request $request)
{
    // check to make sure user is an admin
    $request->user()->authorizeRoles('admin');

    // Display all users that have the role "client"
    // ***** section that does not work ********
    $users = User::all()->roles()->where('name', 'client')->get();

    return view('admin', compact('users'));

}

How can I populate the $users variable with only users who have the role with name "client"?

1
Try going the other direction. Get all roles where name is client, then get all the users that match. - aynber
You can also check Laravel's docs about querying relations, see if any of the methods there work for you. - aynber

1 Answers

8
votes

Use whereHas() method:

User::whereHas('roles', function ($q) use ($roleName) {
    $q->where('name', $roleName);
})->get();