laravel路由应按功能模块拆分至routes/web/等子目录,通过routeserviceprovider::map()显式require加载,避免glob自动扫描;api需按版本前缀隔离,路由命名与中间件配置须统一验证。

路由文件一过百行就难定位、多人协作容易冲突、加个中间件要改七八处——这不是 Laravel 路由写得“多”,是没拆对层级。
按功能模块拆到 routes/web.php 外的独立文件
别把所有路由硬塞进 routes/web.php。Laravel 原生支持按需加载多个路由文件,关键在 RouteServiceProvider::map() 里显式引入。
- 先建目录:
routes/web/下放auth.php、dashboard.php、admin/users.php等,按业务边界切,不是按控制器名切 - 在
RouteServiceProvider的map()方法中用require显式加载,比如:Route::middleware('web')->group(function () { require base_path('routes/web/auth.php'); require base_path('routes/web/dashboard.php'); }); - 每个子文件开头不加
use或namespace,直接写Route::get(...)——因为外层group()已统一处理了中间件和命名空间 - 避免用
glob()自动扫描:它隐式加载、顺序不可控、IDE 跳转失效,调试时你会找不到路由在哪定义的
嵌套分组比平铺 middleware() 更易读
当一组路由同时需要前缀、中间件、命名空间、名称前缀时,用数组形式的 Route::group() 比链式调用更稳,也更容易复用。
当代理已经知道网站路由或内容URL,并且在启动前需要有效的sitemap XML、sitemap索引或robots.txt引用时,请使用sitemap。这是一个发布构件技能,而不是爬虫或SEO平台。
- 错误写法(链式易断、难复用):
Route::middleware('auth')->prefix('admin')->name('admin.')->group(...) - 推荐写法(结构清晰、可抽成配置):
Route::group([ 'prefix' => 'admin', 'middleware' => ['auth', 'can:manage-dashboard'], 'as' => 'admin.', 'namespace' => 'App\Http\Controllers\Admin' ], function () { Route::get('dashboard', [DashboardController::class, 'index'])->name('dashboard'); Route::resource('users', UserController::class)->only(['index', 'show']); }); - 注意:
as和prefix是字符串,不是数组;middleware才是数组,且顺序影响执行逻辑(比如throttle要放在auth后才合理) - 嵌套时别超过三层:
admin → users → import可以,再套一层batch就该考虑是否该拆成新文件了
API 版本路由必须用前缀隔离,别靠控制器分支判断
用 if (app()->version === 'v2') 或在控制器里做版本适配,后期维护成本爆炸。路由层就要把版本切干净。
- 在
RouteServiceProvider::boot()中分别注册:Route::prefix('api/v1')->middleware('api')->group(base_path('routes/api/v1.php')); Route::prefix('api/v2')->middleware('api')->group(base_path('routes/api/v2.php')); - 每个版本文件内不再加
prefix或as,全部由外层统一控制,避免v1.users.index和v2.users.index名称冲突或漏写前缀 -
v1.php和v2.php可共用同一控制器(如API\V1\UserController),但不要让 v2 的路由指向 v1 的控制器方法——语义上已不一致,后续加字段或改状态码会互相污染 - 如果 v2 只改了响应格式,用
Resource类做转换即可,不用动路由或控制器
最常被忽略的一点:路由文件拆得再细,如果没在 php artisan route:cache 前跑 php artisan route:list --name=xxx 验证名称是否唯一、前缀是否叠加正确,上线后 404 或中间件不生效,你得花半小时翻三四个文件才能定位到漏了个 ->name()。










