Laravel 12 路由系统详解:从基础到高级应用
路由是任何Web应用的骨架,它决定了HTTP请求如何被处理。Laravel12
在延续优雅路由风格的同时,引入了更强大的功能。本文将全面解析Laravel12
的路由使用技巧。
基础路由定义
定义基础GET
路由:
// routes/web.php
Route::get('/', function () {
return view('welcome');
});
// 控制器路由
Route::get('/dashboard', [DashboardController::class, 'index']);
支持多种HTTP方法:
Route::post('/users', [UserController::class, 'store']);
Route::put('/users/{id}', [UserController::class, 'update']);
Route::delete('/users/{id}', [UserController::class, 'destroy']);
Route::match(['GET', 'POST'], '/profile', function () {
// 处理GET和POST请求
});
// 处理所有HTTP方法
Route::any('/contact', function () {
// 处理任意类型的请求
});
路由参数处理
必选参数与可选参数:
// 必选参数
Route::get('user/{id}', function ($id) {
return "User ID: " . $id;
});
// 可选参数
Route::get('profile/{name?}', function ($name = 'Guest') {
return "Welcome, " . $name;
});
正则表达式约束:
Route::get('posts/{id}', function ($id) {
return "Post ID: ". $id;
})->where('id', '[0-9]+');
// 多参数约束
Route::get('category/{category}/post/{post}', function ($category, $post) {
// ...
})->where(['category' => '[A-Za-z]+', 'post' => '[0-9]+']);
命名路由与URL生成
定义命名路由:
Route::get('settings', [SettingsController::class, 'show'])
->name('settings.show');
生成URL:
<!-- Blade模板中使用 -->
<a href="{{ route('settings.show') }}">设置</a>
<!-- 带参数 -->
<a href="{{ route('profile', ['name' => 'john']) }}">John's Profile</a>
路由分组与中间件
路由分组:
Route::middleware(['auth'])->group(function () {
Route::get('/account', [AccountController::class, 'index']);
Route::get('/billing', [BillingController::class, 'show']);
});
前缀与子域名路由:
// 路径前缀
Route::prefix('admin')->group(function () {
Route::get('users', [AdminUserController::class, 'index']);
});
// 子域名路由
Route::domain('{store}.example.com')->group(function () {
Route::get('product/{id}', function ($store, $id) {
// ...
});
});
路由特性
缓存路由:
php artisan route:cache // 缓存路由文件
php artisan route:cache --compress // 压缩缓存文件
php artisan route:clear // 清除缓存
动态速率限制
Route::middleware('throttle:rate_limit,1')->group(function () {
// 从数据库或配置读取rate_limit值
});
枚举路由绑定(新增)
enum StatusEnum: string {
case Pending = 'pending';
case Approved = 'approved';
case Rejected = 'rejected';
}
Route::get('/status/{status}', function (StatusEnum $status) {
// URL参数自动转换为枚举实例
return "状态: " . $status->value;
});
资源路由
// 标准资源路由
Route::resource('posts', PostController::class);
// API资源路由(排除create/edit路由)
Route::apiResource('posts', PostController::class);
// 嵌套资源路由
Route::resource('posts.comments', CommentController::class);
// 自定义资源路由
Route::resource('photos', PhotoController::class)->only([
'index', 'show'
])->names([
'index' => 'photos.all'
]);
路由模型绑定
// 隐式绑定(自动注入模型)
Route::get('users/{user}', function (User $user) {
return $user->email;
});
// 自定义绑定逻辑
Route::get('posts/{post:slug}', function (Post $post) {
return $post;
});
视图路由
// 简单视图返回
Route::view('/welcome', 'welcome');
// 带参数的视图
Route::view('/profile', 'profile', ['name' => 'John']);
// 当在使用Inertia.js vue或者react时,可以使用以下代码
Route::get('/inertia', function () {
return Inertia::render('inertia');
});
验证路由列表
php artisan route:list
php artisan route:list --path=api // 仅显示api路由
php artisan route:list --method=GET // 仅显示GET方法路由
跨域资源共享
php artisan config:publish cors
// config/cors.php中配置
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://localhost:3000'],
'allowed_headers' => ['*'],
实践
当管理后台需要配置域名时,开发环境可能不需要配置域名,生产环境需要配置域名,可以使用以下代码:
# bootstrap/app.php中
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
then: function () {
// 后台管理端 这里不要添加前缀,因为后台管理端是通过域名访问的,不需要前缀
Route::middleware('web')->name('admin.')->group(base_path('routes/admin.php'));
},
)
开发环境还是可以直接通过路由访问后台管理端,生产环境需要配置域名,可以使用以下代码:
开发环境访问: http://127.0.0.1/admin/dashboard
生成环境访问: http://admin.example.com/dashboard
# routes/admin.php中
// 根据环境应用域名包装
if (!app()->environment('local')) {
Route::domain(env('APP_DOMAIN', '{store}.example.com'))->group($routeHandler);
} else {
Route::prefix('admin')->group($routeHandler);
}
$routeHandler = function () {
Route::get('/', function () {
return view('welcome')->name('welcome');
});
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard.index');
Route::get('/settings', [SettingsController::class,'show'])->name('settings.show');
Route::middleware(['auth'])->group(function () {
Route::get('/account', [AccountController::class, 'index'])->name('account.index');
Route::get('/billing', [BillingController::class,'show'])->name('billing.show');
});
};
当然,为了避免路由找不到出现404这种情况,页面或者接口中应使用name
的方式生成url
,而不是直接使用url
的方式,这样可以避免路由找不到的情况,例如:
// 正确
<a href="{{ route('admin.dashboard.index') }}">Dashboard</a>
// 错误
<a href="/admin/dashboard">Dashboard</a>
这样还有一个好处就是可以动态的更换后台域名,只需要保持路由的name不变即可
总结
Laravel 12的路由系统在保持简洁语法的同时,通过性能优化和枚举绑定等新特性提升了开发体验。关键要点:
- 使用路由分组组织逻辑
- 善用命名路由生成URL
- 结合路由模型绑定减少冗余代码
- 利用
route:list
调试路由 - 使用Laravel 12的新速率限制保护关键路由
通过合理应用这些特性,可以构建出既高效又易于维护的路由结构,为应用奠定坚实的基础。