Home > Enterprise >  How does Laravel choose between routes that appear the same?
How does Laravel choose between routes that appear the same?

Time:12-29

I am (re-)learning Laravel and chose to do so via an excellent YouTube video in which we built a CRUD app. The app is mostly working very well but I have had a few problems with Laravel not "seeing" some routes until I moved them around in the web.php file.

This is my current web.php file, minus comments and routes used by a second controller:

<?php

use App\Models\Listing;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;
use App\Http\Controllers\ListingController;

//Show the full set of listings.
Route::get('/', [ListingController::class, 'index']);

//Manage listings belonging to the signed-in user
Route::get('/listings/manage', [ListingController::class, 'manage'])->middleware('auth');

//Show form to create job listing
Route::get('/listings/create', [ListingController::class, 'create'])->middleware('auth');

//Store new listing
Route::post('/listings', [ListingController::class, 'store'])->middleware('auth');

//Show form to edit job listing
Route::get('/listings/{listing}/edit', [ListingController::class, 'edit'])->middleware('auth');

//Submit completed edit form to database
Route::put('/listings/{listing}', [ListingController::class, 'update'])->middleware('auth');

//Delete listing from database
Route::delete('/listings/{listing}', [ListingController::class, 'destroy'])->middleware('auth');

//Show a single listing
Route::get('/listings/{listing}', [ListingController::class, 'show']);

My original web.php was exactly the same as this except that the '/listings/manage' route, currently the second in the list, was last. When that happened, every time I tried to invoke the /listings/manage route, the Clockwork browser extension indicated a 404 error and apparently indicated that it was trying to execute the show() method of the ListingController, rather than the manage() method. I was absolutely baffled by this and only eventually solved the problem by moving the /listings/manage route higher up in web.php.

On further testing, I'm finding that I now have the same problem when I'm trying to invoke the destroy() method to delete a listing from the database. Again, I get a 404 error and Laravel seems to be trying to execute the show() method if I am reading Clockwork correctly.

I really don't understand what is going on here with both cases. I could possibly solve the problem by moving the route that is trying to do the destroy() but I don't understand why I'm having the problems in the first place so I want to resolve that FIRST.

Can anyone enlighten me on this matter? I'm particularly curious how Laravel resolves the last three routes in the current web.php since they have the exact same URL, /listings/{listing}, so I'm wondering how it knows whether to invoke update(), destroy() or show().

CodePudding user response:

You have these to routes:

Route::get('/listings/{listing}',[ListingController::class, 'show']);

Route::get('/listings/manage', [ListingController::class, 'manage'])->middleware('auth')

laravel starts from first line of the script and if requested path matches any route return it. So suppose the request /listings/manage.

Laravel routing engine starts from first line of web.php .

First arrives to show method. Request matches it!!

The {listing} parameter could be anything even manage so routing engine stops here and return the show method. Not checking other routes to find more compatible route.

If you put the manage route at top of show so routing engine first arrives to it and matches to it and return it.

CodePudding user response:

Laravel differs in the same routes by their request methods. let's suppose the same path is defined in 3 routes but they have different request methods.(post,put,get). The laravel get the path and match the request method and call that route.

Route::get('laravel/first',function(){});
Route::put('laravel/first',function(){});
Route::delete('laravel/first',function(){});

for more accuracy you may use the names of the routes. As:

Route::get('laravel/first',function(){})->name('getFirstData');
Route::delete('laravel/first',function(){})->name('deleteFirstData');
  • Related