Omer Farooq
Omer Farooq

Reputation: 4074

Single Laravel Route for multiple controllers

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 to the respective controller. The middle ware for this is working fine.

So when manager goes to http://example.com/dashboard he will see the managers dashboard while when admin goes to the same link he can see the admin dashboard.

The below route groups work fine individually but when placed together only the last one works.

/*****  Routes.php  ****/
 // SuperAdmin Routes
    Route::group(['middleware' => 'App\Http\Middleware\SuperAdminMiddleware'], function () {
        Route::get('dashboard', 'SuperAdmin\dashboard@index'); // SuperAdmin Dashboard
        Route::get('users', 'SuperAdmin\manageUsers@index'); // SuperAdmin Users
    });

 // Admin Routes
    Route::group(['middleware' => 'App\Http\Middleware\AdminMiddleware'], function () {
        Route::get('dashboard', 'Admin\dashboard@index'); // Admin Dashboard
        Route::get('users', 'Admin\manageUsers@index'); // Admin Users
    });

I know we can rename the routes like superadmin/dashboard and admin/dashboard but i was wondering if there is any other way to achieve the clean route. Does anyone know of any anywork arounds ?

BTW i am using LARAVEL 5.1

Any help is appreciated :)

Upvotes: 14

Views: 19231

Answers (2)

nCrazed
nCrazed

Reputation: 1035

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.

Upvotes: 8

Alex Kyriakidis
Alex Kyriakidis

Reputation: 2881

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');  
    }
}

Upvotes: 4

Related Questions