Search code examples
phplaravelauthenticationroutesmiddleware

How can I add one route to 2 different middleware (auth) without having to duplicate it in Laravel?


I know this is a basic laravel question but don't know how do it. How can I add one route to 2 different middleware (auth) without having to duplicate it?

// =admin
Route::group(['middleware' => ['auth']], function() {
    Route::get('/dashboard', 'App\Http\Controllers\DashboardController@index')->name('dashboard');
    Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
});
// =cashier
Route::group(['middleware' => ['auth', 'role:cashier']], function() {
    Route::get('/dashboard/cashier/profile', 'App\Http\Controllers\DashboardController@showCashierProfile')->name('dashboard.cashier.profile');
    Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
});

I have this route and I don't want to repeat calling this per auth middleware: Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');


Solution

  • You can't have two routes with the same url.

    Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
    

    This route is inside both groups and since the url they will produce will be the same, only the second will remain.

    Route::group(['middleware' => ['auth']], function() {
        Route::get('/dashboard', 'App\Http\Controllers\DashboardController@index')->name('dashboard');
        //Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
    // this route will be ignored because the other one has the same url
    });
    
    Route::group(['middleware' => ['auth', 'role:cashier']], function() {
        Route::get('/dashboard/cashier/profile', 'App\Http\Controllers\DashboardController@showCashierProfile')->name('dashboard.cashier.profile');
        Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
    });
    

    If you want Laravel to handle these two routes differently, you have to add a prefix:

    Route::group(['prefix' => 'admin', 'as' => 'admin.', 'middleware' => ['auth']], function() {
        Route::get('/dashboard', 'App\Http\Controllers\DashboardController@index')->name('dashboard');
        //Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
    // this route will be ignored because the other one has the same url
    });
    
    Route::group(['prefix' => 'cashier', 'as' => 'cashier.',  'middleware' => ['auth', 'role:cashier']], function() {
        Route::get('/dashboard/cashier/profile', 'App\Http\Controllers\DashboardController@showCashierProfile')->name('dashboard.cashier.profile');
        Route::get('make-a-sale', [PurchasesController::class, 'index'])->name('make-a-sale.index');
    });
    

    This way, when the url will be prefixed with admin, the first route will be called (without the role:cashier middleware).

    Notice that I added a route name prefix ('as' => 'admin.' / 'as' => 'cashier.') so you can call each one by name, using:

    route('admin.make-a-sale.index'); // admin/make-a-sale
    //or
    route('cashier.make-a-sale.index'); // cashier/make-a-sale