@aassdds
Люблю борщ и PHP

Как реализовать вызов разных контроллеров на одну и ту же ссылку, исходя из роли авторизованного юзера?

Добрый день
laravel 5.8
Вот мой НЕ работающий код
routes/web.php:
Route::group(['middleware'=>'auth'], function() {
    Route::group(['middleware'=>'role:administrator'], function(){
        Route::get("api/users",  'Admin\\UserController@get_list');
    }); // administrator

    Route::group(['middleware'=>'role:resident'], function(){
        Route::get("api/users", 'Resident\\UserController@get_list');
    }); // resident
});


RoleMiddleware:
class RoleMiddleware
{
    public function handle($request, Closure $next, $role)
    {
        if (auth()->user() && auth()->user()->role == $role) {
            return $next($request);
        }
        return $request;
    } // func
}


Как вы видите из кода, мне бы хотелось:
авторизованный юзер открывает ссылку api/users
Если его роль admin - то срабатывает Admin\\UserController@get_list
Если его роль resident - то Resident\\UserController@get_list
Если его роль еще какая то - то 404
Если НЕ авторизованный юзер - то тоже 404

Как это работает сейчас
авторизованный юзер с ролью resident открывает ссылку api/users
срабатывает Resident\\UserController@get_list
тут все отлично

авторизованный юзер с ролью admin открывает ссылку api/users
Вылетает Argument 1 passed to Illuminate\Session\Middleware\StartSession::addCookieToResponse() must be an instance of Symfony\Component\HttpFoundation\Response, boolean given
Если посмотреть что происходит в RoleMiddleware - то в последний параметр $role попадает только значение "resident"
До проверки на admin не доходит
Получается, как только middleware встретила "не подходящий" запрос - все падает
Остальные роуты, которые могут подойти не проверяются - и вот это я хочу исправить

Можно ли сделать такую фильтрацию именно на уровне routes / middlewares
И если "да" - то как ?
  • Вопрос задан
  • 159 просмотров
Решения вопроса 1
smilingcheater
@smilingcheater
В миддлваре пишите код, который определяет какой контроллер должен обрабатывать реквест, примерно так:
$user = Auth::user();
if ($user?->isAdmin()) {
    $controller = \Controllers\Admin\IndexController::class;
} elseif ($user?->isManager()) {
    $controller = \Controllers\Manager\IndexController::class;
} else {
    abort(403);
}

Дальше - подменяете параметры роута:
$route = $request->route();
$action = $route->getAction();
// подменяем на новый
$action['uses'] = "$controller@$actionMethod";
$action['controller'] = "$controller@$actionMethod";
// сохраняем
$route->setAction($action);
// нужно сбросить контроллер, иначе отрабатывает старый
$route->controller = false;
return $next($request);
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Fragster
@Fragster
помогло? отметь решением!
Сделать контракт (интерфейс) с нужными методами (которые есть у контроллера), в зависимости от авторизованного юзера замапить реализацию https://laravel.com/docs/8.x/container#binding-int...
в роуте использовать контракт
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы