Laravel路由匹配异常:访问books.archives触发404跳转至books.display
问题根源
Laravel 路由采用从上到下的顺序匹配规则,只要命中第一个符合规则的路由就会停止后续匹配,artisan route:list 的输出排序不代表路由实际匹配顺序,匹配顺序完全以你在路由文件中编写的先后顺序为准。
你当前的路由注册顺序存在问题:将带动态参数的 Route::get('/{bookInfo}', [BooksController::class, 'display'])->name('.display'); 放在了 archives 路由分组的前面。当你访问 /dashboard/books/archives 时,Laravel 会直接把路径中的 archives 识别为 {bookInfo} 参数,命中 books.display 路由,不会继续匹配后面的 archives 分组路由。
由于 {bookInfo} 一般是开启了模型绑定的参数,传入字符串 archives 无法匹配到对应数据库记录,就会直接抛出 404 错误,和你遇到的现象完全一致。
另外你路由中还有一个潜在问题:Route::post('/delete/{id}', [BooksController::class, 'delete'])->name('.delete'); 也放在了参数路由的后面,后续访问 /books/delete/xxx 时同样会被 books.display 路由拦截,也需要调整顺序。
解决方法
遵循固定路径路由优先于同层级动态参数路由的原则,调整路由注册顺序:将所有固定前缀的路由(包括 archives 分组、delete 路由)全部放在 /{bookInfo} 动态参数路由的前面即可。
修改后的路由代码如下:
// Books Route::prefix('books')->name('books')->group(function() { Route::get('/', [BooksController::class, 'list']); Route::get('/create', [BooksController::class, 'create'])->name('.create'); Route::post('/', [BooksController::class, 'store'])->name('.store'); Route::get('/edit/{bookInfo}', [BooksController::class, 'edit'])->name('.edit'); Route::patch('/edit/{bookInfo}', [BooksController::class, 'update'])->name('.update'); Route::post('/delete/{id}', [BooksController::class, 'delete'])->name('.delete'); // archives 分组放在动态参数路由前 Route::prefix('archives')->name('.archives')->group(function() { Route::get('/', [BooksController::class, 'archived']); Route::get('/{bookInfo}', [BooksController::class, 'archive'])->name('.store'); Route::post('/delete/{bookInfo}', [BooksController::class, 'delete'])->name('.delete'); Route::post('/delete/all', [BooksController::class, 'deleteAll'])->name('.delete.all'); Route::get('/restore/{id}', [BooksController::class, 'restore'])->name('.restore'); }); // 带动态参数的路由放在同层级最后 Route::get('/{bookInfo}', [BooksController::class, 'display'])->name('.display'); });
修改完成后执行 php artisan route:clear 清空路由缓存即可生效。
内容的提问来源于stack exchange,提问作者Shekenz

