Я использую laravel 5.5, где я разрабатываю Аутентификацию на основе ролей для пользователей. Пользователь системы может иметь несколько ролей, и эти роли могут иметь доступ к нескольким меню. Я хочу проверить, есть ли у текущих ролей пользователя доступ к определенному меню.
Ниже приведена структура моей таблицы
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
});
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->longText('description')->nullable();
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
});
Schema::create('role_user', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('role_id');
$table->integer('is_default')->default(0);
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')->on('roles')
->onDelete('cascade');
});
Schema::create('menus', function (Blueprint $table) {
$table->increments('id');
$table->integer('parent_id');
$table->string('name')->unique();
$table->string('action')->unique();
$table->integer('sequence');
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
});
Schema::create('menu_roles', function (Blueprint $table) {
$table->increments('id');
$table->integer('menu_id');
$table->integer('role_id');
$table->timestamps();
$table->dateTime('deleted_at')->nullable();
$table->foreign('menu_id')
->references('id')->on('menus')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')->on('roles')
->onDelete('cascade');
});
Я определил отношения следующим образом:
User.php
public function roles()
{
return $this->belongsToMany(Role::class);
}
Role.php
public function users()
{
return $this->belongsToMany(User::class);
}
public function menus()
{
return $this->belongsToMany(Menu::class);
}
Как я могу проверить, есть ли у определенной роли доступ к определенному меню?
Заранее спасибо
4 ответа
Вы можете проверить это в User и в Role ... я бы сделал это в User Model
Нечто подобное должно работать в пользовательской модели ... для роли, просто удалите пользовательские таблицы.
public function checkMenuPermission($key)
{
// YOUR KEY can be name, id, any unique column...
$results = DB::table('users')
->join('role_user', 'users.id', '=', 'role_user.user_id')
->join('menu_roles', 'role_user.role_id', '=', 'menu_roles.role_id')
->join('menus', 'menus.id', '=', 'menu_roles.menu_id')
->select('menus.name')
->where('users.id', $this->id)
->where('menus.name', $key)
->orderBy('menus.name')
->distinct()
->get()->count();
return $results > 0 ? true : false;
}
Тогда в ваших контроллерах просто можно назвать это как $user->checkMenuPermission('someSome');
Изменить
Если вы хотите сделать это только с Eloquent , вы можете
public function checkMenuPermission($key){
foreach($this->menus as $m){
if($m->name == $key){
return true;
}
}
return false;
}
Предполагая, что у вас есть переменная типа $menuId
, вы можете просто использовать whereHas () с аутентифицированным пользователем и проверьте, существуют ли отношения:
$canAccess = auth()->user()->whereHas('roles.menus', function ($query) use($menuId) {
$query->where('id', $menuId);
})->exists();
Вы знаете, как работают политики? Это должно вам очень помочь в этом случае. Е.Г .: Вы можете создать файл MenuPolicy, в который вы поместите всю логику ограничений / авторизаций для меню. А затем просто используйте директиву @can в блейд-файле меню в соответствии с вашими правилами
Проверьте там https://laravel.com/docs/5.6/authorization#creating-policies
Вы должны создать еще одну сводную таблицу, что-то вроде
Schema::create('role_menu', function (Blueprint $table) {
$table->increments('id');
$table->integer('menu_id');
$table->integer('role_id');
$table->foreign('menu_id')
->references('id')->on('menus')
->onDelete('cascade');
$table->foreign('role_id')
->references('id')->on('roles')
->onDelete('cascade');
});
Очевидно, должна быть таблица menus
.
Чем больше возможностей открывается ... Я думаю, что лучший способ - создать промежуточное ПО, которое можно использовать для маршрутов конкретного меню.
Например:
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// Check user roles in order to check if role has access to the menu
foreach($request->user()->roles as $role) {
// This code supposes that your route is something like http://app.tld/menus/{menu_id}
if($role->menus()->find($request->route('menu_id'))) {
return $next($request);
}
}
// Otherwise abort, redirect.. whatever
abort(401);
}
Похожие вопросы
Новые вопросы
laravel
Laravel - это бесплатная веб-инфраструктура PHP с открытым исходным кодом, созданная Тейлором Отвеллом и предназначенная для разработки веб-приложений по архитектурному шаблону модель-представление-контроллер (MVC) на основе Symfony. Исходный код Laravel размещен на GitHub и лицензирован в соответствии с условиями лицензии MIT.