Intereting Posts
Может ли PHP распаковать файл, сжатый классом .NET GZipStream? Компилировать файл C ++ с помощью PHP Задайте заголовок авторизации с помощью PHP и curl Regex допускает только 1 символ Возможно ли доступ к внешней локальной переменной в PHP? Как избежать дублирования содержимого, хранящегося в базе данных MySQL, предоставленной пользователем Какой самый безопасный способ обнаружения языка браузера и перенаправление 301 на домашнюю страницу quickblox javascript sdk один к одному видеочат Использование регулярного выражения subpattern to вместо использования регулярного выражения 2 раза в php Попытка получить общую сумму на основе ввода пользователем Странное поведение оператора ++ в PHP 5.3 2 Ячейки ввода автозаполнения / предложения с использованием jQuery или Ajax со вторым ящиком на основе первых выборок с несколькими элементами 5-минутный кэш файлов в PHP Как узнать, используете ли вы HTTPS без $ _SERVER PHP: математические вычисления и сравнения

Пользователи, роли и действия Laravel 5.1

Я создаю приложение, использующее Laravel 5.1 с пользователями , ролями и действиями .

Настройка таблицы выглядит так:

пользователь

id name 1 John Smith 2 Fred Smith 

роль

 id name 1 Administrator 2 Customer 

role_user

 user_id role_id 1 1 2 1 

действие

 id name description path 1 dashboard ability to access dashboard /admin 2 editAdmin ability to edit admins /admin/users/administrators/{id}/edit 

action_role

 action_id role_id 1 1 2 1 

В таблице user содержатся ВСЕ пользователи на сайте, включая администраторов и клиентов.

Таблица role содержит все возможные роли, которые может иметь пользователь. Например, администратор или клиент .

Таблица role_user представляет собой role_user таблицу, которая связывает role с user .

В таблице action перечислены все возможные действия (например, URL-адреса или маршруты) в приложении.

action_role – сводная таблица, которая связывает action с role .

Итак, подведем итог:

  • У пользователей есть роли
  • Роли имеют действия
  • Пользователь может иметь много ролей
  • Роль может иметь много действий

Я хочу иметь промежуточную установку, которая проверяет загрузку страницы, если у пользователя есть разрешения на просмотр текущей страницы. Чтобы сделать это, мне нужно иметь доступ к действиям пользователей, используя такой вызов:

 $user->roles()->actions(); 

Как настроить мои красноречивые отношения для поддержки такого вызова?

ОБНОВИТЬ

Мои отношения настроены так в моих моделях:

пользователь

 /** * The roles that belong to the user. * * @return Object */ public function roles() { return $this->belongsToMany('App\Models\User\Role')->withTimestamps(); } 

Роль

 /** * The actions that belong to the role. * * @return Object */ public function actions() { return $this->belongsToMany('App\Models\User\Action'); } /** * The users that belong to the role. * * @return Object */ public function users() { return $this->belongsToMany('App\Models\User\User'); } 

действие

 /** * The roles that belong to the action. * * @return Object */ public function roles() { return $this->belongsToMany('App\Models\User\Role'); } 

Eloquent не имеет отношения HasManyThrough через две сводные таблицы.


1. Вы можете получить действия от ленивой нетерпеливой загрузки ролей и действий, а затем извлечь их:

 $actions = $user->load('roles.actions')->roles->pluck('actions')->collapse()->unique(); 

2. Вы можете проверить действие непосредственно в базе данных, используя ограничение whereHas :

 $allowed = $user->roles()->whereHas('actions', function ($query) use ($action) { $query->where('name', $action); })->exists(); 

Для обработки пользовательских ролей и пользовательских разрешений вы можете просто использовать пакет Toddish .

Есть много вещей, которые этот пакет делает для вас. как:

 $user->is('Your Defined Role'); $user->can('add_user'); $user->level(7); 

Для установки просто прочитайте его документацию.

Хотя вы уже упоминали, что ваши модели Eloquent (и их отношения) настроены, я предполагаю, что в вашем приложении уже есть следующее:

Модель пользователя

 class User extends Eloquent { public function roles() { return $this->belongsToMany('App\Models\Role'); } } 

Ролевая модель

 class Role extends Eloquent { public function actions() { return $this->belongsToMany('App\Models\Action'); } public function users() { return $this->belongsToMany('App\Models\User'); } } 

Модель действия

 class Action extends Eloquent{ public function roles(){ return $this->belongsToMany('App\Models\Role'); } } 

Учитывая, что это правильно установлено, вы не можете сделать такой вызов, как следующее: Laravel предположит, что вы делаете вызов метода Query Builder или чего-то еще [этого на самом деле не существует]:

 $userActions = App\Models\User::find(1)->roles()->actions(); 

Вместо этого вы должны использовать магический метод Laravel whereHas для запроса отношений, в которых задействованы несколько вложенных отношений.

Теперь, имея id пользователя и текущее допустимое action [ которое действительно может быть использовано в вашем промежуточном программном обеспечении ], можно определить, разрешено ли пользователю видеть страницу:

 $hasAccess = App\Models\User::whereHas('roles.actions', function($q) use ($id, $action){ $q->where('users.id', $id); $q->where('actions.name', $action); })->get()->toArray(); if($hasAccess){ // or `count($hasAccess) > 0`. The former will work since any number > 0 evaluates to true in PHP //user has access } 

Обратите внимание на вложение отношений . ,


Существование отношений в Ларавеле :

В Laravel существование взаимосвязи между моделями определяется с whereHas методов has и whereHas . Метод has используется для определения того, существует ли связь , например, при выполнении App\User::has('roles')->get() вы всегда получите список / коллекцию пользователей, которые, по крайней мере, имеют какие-либо роли . Больше энергии для этого можно добавить с помощью whereHas с помощью которого вы можете добавить where предложения к фактическому запросу.

Привет, вот как я решил это.

Я не использовал таблицу действий. Просто пользователи , роли и таблица user_role . После решения я передаю свое собственное промежуточное программное обеспечение для массива ролей для каждого создаваемого мной маршрута:

 Route::get('insights',[ 'as'=>'insights', **'middleware'=>['access.level'],** **'roles'=>['admin','customer'],** 'uses'=>'CustomersController@index' ]); 

Измененные файлы: приложение \ Http \ Controllers \ Controller.php Пользовательское промежуточное ПО: приложение CheckAccessLevel \ Http \ Kernel.php app \ Http \ routes.php

Controller.php В этом файле я хотел бы загрузить загружаемого текущего пользователя с его ролями и сделать его глобальной переменной во всех представлениях как {{currentUser}} и во всех моих контроллерах как «$ this-> currentUser» . это код:

  protected $currentUser; public function __construct() { if(isset(Auth::user()->username)){ $this->currentUser = User::with('roles')->where(['username' => Auth::user()->username])->first(); // Share this property with all the views and controllers in your application. view()->share('currentUser', $this->currentUser); } } 

Пользовательское промежуточное ПО: CheckAccessLevel.php

Здесь, в промежуточном программном обеспечении, я извлекаю массив ролей, переданный на маршрут, а также роли, назначенные текущему пользователю. После того, как я получу эти переменные, я пересекаю их, чтобы увидеть, есть ли совпадение, прежде чем я включу пользователя. проверьте код ниже:

 //if user is not logged in, show them where to login :) if (!Auth::check()) { return redirect()->route('user::login'); } //Otherwise get the roles for that route $get_route_action = $request->route()->getAction(); $get_route_roles = $get_route_action['roles']; //Eager load the user with their list of roles $eager_user = User::with('roles')->where(['id'=>$request->user()->id])->first(); $user_roles = $eager_user->roles->pluck('role_name')->toArray(); //intersect the users roles with the route roles to see if there is a match foreach ($user_roles as $user_role){ if(in_array($user_role, $get_route_roles)){ return $next($request); } } 

Kernel.php здесь, я регистрирую свой маршрут как «access.level» внутри группы промежуточного программного обеспечения маршрута

Route.php, тогда всякий раз, когда я создаю маршрут, я просто передаю ему разрешенные имена и voala! Меня устраивает..

Надеюсь, это поможет.

Здесь вам нужны отношения HasManyThrough. Вот вам кое-что, чтобы вы начали.

Судя по вашим данным таблицам, я вижу, что у него есть отношения «один ко многим» с пользователем и ролями. Хотя действие и роли также имеют отношения «многие ко многим».

Но сначала вам нужно создать модели для каждого объекта (пользователя, роли, действия), чтобы следовать структуре MVC. Вы можете легко сделать эти модели из командной строки с помощью мастера Laravel с помощью этой команды.

 php artisan make:model User 

Обязательно добавьте или измените столбцы во вновь созданных миграциях. Предполагая, что у вас также установлены сводные таблицы для трех таблиц, теперь вы можете добавить отношения.

 class User extends Model { // protected $table = 'users'; /* * @var table * */ public function action() { return $this->hasManyThrough('App\Action', 'App\Role'); } } 

Теперь у вас есть отношения HasManyThrough . вы можете запросить это прямо, не нужно включать роль.

  //this $actions = User::find(1)->action(); //instead of $actions = User::find(1)->role()->action(); //this will return all actions available to a user with id of 1 

ПРИМЕЧАНИЕ. Я также предлагаю вам настроить свою роль и пользовательские модели на отношения один к одному.