Search code examples
phplaravellaravel-routing

Laravel route conflict


I have two routes:

Route::get('subjects/{subject}/{tag?}', 'SubjectController@show');
Route::get('subjects/{subject}/{tag}/{lesson}','LessonController@show');

When I hit the first route, it works properly but when I hit the second route, I get the following error response:

Sorry, the page you are looking for could not be found.

Is this because laravel is trying to treat the /{tag}/{lesson} portion of 2nd route as the value of the parameter of 1st route?

My controller methods are as follows:

//SubjectController.php
public function show($subjectSlug, $tag = null)
{
    dd('Inside SubjectController@show');    
}

//LessonController.php
public function show(Subject $subject, Tag $tag, Lesson $lesson)
{
    dd('Inside LessonController@show'); 
}

When I visit, say,

localhost:3000/subjects/mysubject-slug/1

It matches the first route and responds accordingly, but when I visit,

localhost:3000/subjects/mysubject-slug/1/mylesson-slug

it shows the page not found error. How can I fix this?


Solution

  • As mentioned in the comments, because of Route Model Binding you can end up with a 404 when the model for the binding can not be retrieved. When using implicit route model binding the primary key will be used to search against by default. This can be changed on the model to use a different field, in this case the slug field.

    "If you would like model binding to use a database column other than id when retrieving a given model class, you may override the getRouteKeyName method on the Eloquent model"

    Laravel 5.5 Docs - Routing - Route Model Binding - Implicit Binding

    public function getRouteKeyName()
    {
        return 'slug';
    }