Laravel web.php 中的路线顺序问题

Laravel Route issues with Route order in web.php

我在 Laravel 中遇到路由问题,我正在学习一个教程,我们在 web.php 文件

中列出了这些路由
Route::get('/home', 'HomeController@index')->name('home');
Route::get('/blog', 'BlogController@index')->name('blog');
Route::get('/blog/create', 'BlogController@create');
Route::post('/blog/store', 'BlogController@store');
Route::get('/blog/{id}', 'BlogController@show');
Route::get('/blog/{id}/edit', 'BlogController@edit');
Route::patch('/blog/{id}', 'BlogController@update');
Route::delete('/blog/{id}', 'BlogController@destroy');
Route::get('/blog/bin', 'BlogController@bin');

问题出在通往 blog/bin 的最后一条路线上,如果我把它放在下面,它就无法正常工作,但是在教程中,我们已将它移到其他路线的顶部,然后它就可以正常工作,讲师说那里路线是否存在冲突,最后一条路线需要位于顶部才能工作,但根本没有解释为什么?任何人都可以详细解释一下,因为我真的刚刚开始 Laravel...

您不能在路由参数上定义类型。所以 Laravel 猜测你的参数可以是 Integer 甚至是 String。

基于此,如果您尝试访问 /blog/bin。 Laravel 将尝试在 id 参数中使用路由 /blog/{id} 和 "bin"。

这里有一个比我更好的答案:https://laracasts.com/discuss/channels/laravel/order-of-routes-being-applied/replies/149199

访问一条路线时,Laravel 从上到下遍历您的路线列表,直到找到 'matches' 一条路线,然后立即选择这条路线。

在您的示例中,当尝试使用 GET 访问 /blog/bin 时,它有两个潜在的匹配项:

Route::get('/blog/{id}', 'BlogController@show');

Route::get('/blog/bin', 'BlogController@bin');

在这种情况下,Route::get('/blog/{id}', 'BlogController@show'); 排在第一位,因此它会被选中。

正如前面的答案正确指出的那样,将 /blog/bin 路线放在 /blog/{id} 路线上方可以解决问题。但是,这 'solution' 会让您在将来犯类似的错误(例如,当定义一个 /blog/example 路由并意外地将其放在 /blog/{id} 下时)。另外,我个人认为让你的路由功能依赖于放置它们的顺序并不是很优雅。

在我看来,在可能的情况下,更稳健的解决方案是限制 /blog/{id} 接受的可能值 regex constraint

例如,如果您为您的博客post使用数字 ID,您知道如果 id 是一个数字,您只想使用路由 /blog/{id}。因此,您可以按如下方式定义路线:

Route::get('/blog/{id}', 'BlogController@show')->where('id', '[0-9]+');

当然这通常是不可能的,例如,如果您将 post 标题用作 id,但如果有某种方法可以区分 post id 从任何其他 /blog/foo 路线,那么这是可能的。