Search code examples
laravelrouteslaravel-blade

Laravel 8 route order from bottom to top


I have installed Laravel 8 and work perfectly, and then i tried to learn about routing and try to make some routes like this

Route::view('testing', 'welcome')->name('testingWelcome');
Route::get('testing',[TestingController::class, 'noParameter'])->name('testingNoParam');
Route::view('testing', 'dashboard')->name('testingDashboard');

Some post in here said that routes in web.php work from top to bottom. But, thats not what i get when i called in url http://localhost/laraps/public/testing. it always called the bottom one. i tried to change the order, but still the last one always get called.

Any explanation for this one? or am i made any wrong configuration?

thanks for any help


Solution

  • A short explanation for this would be that each call to Route::{verb} creates a new route entry under your route collection (relevant code). {verb} can be any HTTP verb e.g. get, or post etc. This entry is created under an array entry [{verb}][domain/url].

    This means that when a new route is registered that matches the same URL with the same method it will overwrite the old one.

    So in the case

    Route::view('testing', 'welcome')->name('testingWelcome');
    Route::get('testing',[TestingController::class, 'noParameter'])->name('testingNoParam');
    Route::view('testing', 'dashboard')->name('testingDashboard');
    

    Only the 3rd declaration actually "sticks". There are cases where multiple route definitions can match the same URL for example assume you have these routes:

    Route::view('testing', 'welcome')->name('testingWelcome');
    Route::get('testing/{optionalParameter?}',[TestingController::class, 'parameter'])->name('testingNoParam');
    Route::view('testing/{otherParameter?}', 'dashboard')->name('testingDashboard');
    

    In this case all 3 routes are added to the route collection, however when accessing URL example.com/testing the first matched route will be the one that will be called in this case the welcome view. This is because since all 3 routes are declared, once the router finds one matching route, it stops looking for more matches.

    Note: There's generally no point in declaring multiple routes with the exact same URL so this is mainly an academic exercise. However there is often a use case for cases like e.g. model/{id} and model/list` to differentiate between getting info for a specific model and getting a list of models. In this case it's important to declare the routes as:

    Route::get('model/list',  [ ModelController::class, 'list' ]);
    Route::get('model/{id}',  [ ModelController::class, 'view' ]);
    

    However you can be more explicit in route declarations using:

    Route::get('model/{id}',  [ ModelController::class, 'view' ])->where('id', 
    '\d+');
    Route::get('model/list',  [ ModelController::class, 'list' ]);
    

    in this case the order does not matter because Laravel knows id can only be a number and therefore will not match model/list