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
路线,那么这是可能的。
我在 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
路线,那么这是可能的。