简体   繁体   中英

Filter Users by role Laravel

I have a small Laravel app with several users and different roles.

What I want is to have a different page to display the users according to their roles (a page to see the admins, a page to see the students etc...)

I have a Users table (of course), a Roles table and a role_user table

Roles :

Schema::create('roles', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });

role_user table :

Schema::create('role_user', function (Blueprint $table) {
        $table->id();
        $table->BigInteger('role_id')->unsigned()->onDelete('cascade');
        $table->BigInteger('user_id')->unsigned()->onDelete('cascade');
        $table->timestamps();
    });

I know that it will seem easy to a lot of you, but not to me. I'm stuck...

Thanks a lot !

You don't really need a link table for user roles. It can be done much easier with just a Roles table. Let me explain:

First you can make a migration for the roles table. I assume you already have that table but if not, this is how you can create one

php artisan make:migration create_roles_table

And you can fill in the fields accordingly. To make the relation with the user you need to add a role function to the user model. So in your user model you can say

/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function role()
{
    return $this->belongsTo(Role::class);
}

In your Roles model you can do the same but the other way around. If you not already have a Roles model you can easily create one using php artisan make:model Roles . You can add this to the Roles model to make the relation complete:

public function users()
    {
        return $this->hasMany(User::class);
    }

Assuming you want multiple users with the same role the above is the correct way

As last you need to add a role_id field to the user to make the relation complete. You can do this by adding $table->integer('role_id') to your user migration.

If all set and done you can do something like $user->role->name to get the name of the role (Assuming you have a field called name in your roles table) and you can add different rules accordingly. For instance using middleware

You can create a middleware for this exact reason. php artisan make:middleware name

And you can do something like this

class RoleAllowedMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $allowed_ids =[1,2];

        if(!in_array($request->user()->role_id, $allowed_ids)) {
            return redirect('/');
        }
        return $next($request);
    }
}

To make certain routes only accessible for users with a specific role

I hope this is what you are looking for!

you can do it using double join:

 $roleName = 'admin';
        $adminUsers = DB::table('users')->join('role_user', 'users.id', 'role_user.user_id')
            ->join('roles', 'role_user.role_id', 'roles.id')
            ->where('roles.name', $roleName)->get();

or the better solution is using laravel many to many relation

after building the relation like in doc, you can do it using whereHas:

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

You can maintain a one to many relationships between roles and users by adding these two methods in their model files.

User.php

public function roles() {
        return $this->belongsToMany('App\Models\Role', 'role_user');
}

Role.php

public function users()
    {
        return $this->belongsToMany('App\Models\User', 'role_user');
    }

So, you can then simply fetch all the users belonging to that particular role by using something like Role::find(1)->users;

Thank you all for your answers.

I finally found an answer to my question (I did not see your posts before...)

This is what I do :

public function admins()
{

    $adminRole = Role::where('name', 'admin')->first();
    $admins = $adminRole->users;

    return view('admin.users.admins', compact('admins'));
}

It works fine but if there's a better way, I'd be happy to learn it ;)

Thank you all.

Peace

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM