Route precedence order

2019-07-07 17:45发布

问题:

I have 2 routes with their methods written in same controller[LinkController]:

Route::get('/{country}/{category}', ['as' => 'tour.list', 'uses' => 'LinkController@tourlist']);

Route::get('/{category}/{slug}',['as' => 'single.tour', 'uses' => 'LinkController@singleTour']);

And my methods are:

public function tourlist($country, $category)
{
    $tour = Tour::whereHas('category', function($q) use($category) {
            $q->where('name','=', $category);
        })
        ->whereHas('country', function($r) use($country) {
            $r->where('name','=', $country);
        })
        ->get();
    return view('public.tours.list')->withTours($tour);
}
public function singleTour($slug,$category)
{
    $tour = Tour::where('slug','=', $slug)
              ->whereHas('category', function($r) use($category) {
            $r->where('name','=', $category);
        })
        ->first();
    return view('public.tours.show')->withTour($tour);
}

My code in view is:

<a href="{{ route('single.tour',['category' => $tour->category->name, 'slug' => $tour->slug]) }}">{{$tour->title}}</a>

The trouble i am having is the second route [single.tour] returns the view of the first route [tour.list]. I tried to return other view also in 2nd method but still it returns the view of first method. Does laravel have routing precedence ?

回答1:

This is happening because, Laravel matches routes from the file, and the route which comes earlier and matches the pattern will execute first, you can use regex pattern technique to avoid this like:

Route::get('user/{name}', function ($name) {
    //
})->where('name', '[A-Za-z]+'); // <------ define your regex here to differ the routes

See Laravel Routing Docs

Hope this helps!



回答2:

Both your routes consist of two parameters in the same place. That means any url that matches route 1 will also match route 2. No matter in what order you put them in your routes definition, all requests will always go to the same route.

To avoid that you can specify restrictions on the parameters using regular expressions. For example, the country parameter may only accept two letter country codes, or the category parameter may have to be a numeric id.

Route::get('/{country}/{category}')
    ->where('country', '[A-Z]{2}')
    ->where('category', '[0-9]+');

https://laravel.com/docs/5.3/routing#parameters-regular-expression-constraints