I am creating a project where i have multiple user types, eg. superadmin, admin, managers etc. Once the user is authenticated, the system checks the user type and sends him
The best solution I can think is to create one controller that manages all the pages for the users.
example in routes.php file:
Route::get('dashboard', 'PagesController@dashboard');
Route::get('users', 'PagesController@manageUsers');
your PagesController.php file:
protected $user;
public function __construct()
{
$this->user = Auth::user();
}
public function dashboard(){
//you have to define 'isSuperAdmin' and 'isAdmin' functions inside your user model or somewhere else
if($this->user->isSuperAdmin()){
$controller = app()->make('SuperAdminController');
return $controller->callAction('dashboard');
}
if($this->user->isAdmin()){
$controller = app()->make('AdminController');
return $controller->callAction('dashboard');
}
}
public function manageUsers(){
if($this->user->isSuperAdmin()){
$controller = app()->make('SuperAdminController');
return $controller->callAction('manageUsers');
}
if($this->user->isAdmin()){
$controller = app()->make('AdminController');
return $controller->callAction('manageUsers');
}
}
You can do this with a Before Middleware that overrides the route action's namespace, uses and controller attributes:
use Closure;
use Illuminate\Http\Request;
use Illuminate\Contracts\Container\Container;
use App\Http\Middleware\AdminMiddleware;
use App\Http\Middleware\SuperAdminMiddleware;
class AdminRoutingMiddleware
{
/**
* @var Container
*/
private $container;
public function __construct(Container $container)
{
$this->container = $container;
}
private static $ROLES = [
'admin' => [
'namespace' => 'Admin',
'middleware' => AdminMiddleware::class,
],
'super' => [
'namespace' => 'SuperAdmin',
'middleware' => SuperAdminMiddleware::class,
]
];
public function handle(Request $request, Closure $next)
{
$action = $request->route()->getAction();
$role = static::$ROLES[$request->user()->role];
$namespace = $action['namespace'] . '\\' . $role['namespace'];
$action['uses'] = str_replace($action['namespace'], $namespace, $action['uses']);
$action['controller'] = str_replace($action['namespace'], $namespace, $action['controller']);
$action['namespace'] = $namespace;
$request->route()->setAction($action);
return $this->container->make($role['middleware'])->handle($request, $next);
}
}
This way you have to register each route only once without the final namespace prefix:
Route::group(['middleware' => 'App\Http\Middleware\AdminRoutingMiddleware'], function () {
Route::get('dashboard', 'dashboard@index');
Route::get('users', 'manageUsers@index');
});
The middleware will convert 'dashboard@index' to 'Admin\dashboard@index' or 'SuperAdmin\dashboard@index' depending on current user's role attribute as well as apply the role specific middleware.