路由分组与中间件
High Contrast
Dark Mode
Light Mode
Sepia
Forest
1 min read188 words

路由分组与中间件

Laravel 的路由不只是"URL 映射到函数"。通过路由分组、命名路由和中间件,你可以在路由层面统一处理认证检查、API 版本、速率限制——而不是在每个控制器里重复写相同的逻辑。


基础路由语法

// routes/web.php
use App\Http\Controllers\TaskController;
use Illuminate\Support\Facades\Route;
// 基础 HTTP 动词
Route::get('/tasks', [TaskController::class, 'index']);
Route::post('/tasks', [TaskController::class, 'store']);
Route::get('/tasks/{task}', [TaskController::class, 'show']);
Route::put('/tasks/{task}', [TaskController::class, 'update']);
Route::delete('/tasks/{task}', [TaskController::class, 'destroy']);
// 快捷方式:资源路由(生成以上全部)
Route::resource('tasks', TaskController::class);
// API 资源路由(排除 create/edit 页面路由)
Route::apiResource('tasks', TaskController::class);
// 命名路由(用于生成 URL)
Route::get('/tasks/{task}', [TaskController::class, 'show'])->name('tasks.show');
// 使用:route('tasks.show', $task)  → /tasks/42

路由分组:统一配置

// routes/api.php
use Illuminate\Support\Facades\Route;
// 认证 + 速率限制
Route::middleware(['auth:sanctum', 'throttle:api'])
->prefix('v1')
->name('api.v1.')
->group(function () {
// 任务管理
Route::apiResource('tasks', TaskController::class);
// 团队协作(仅 premium 用户)
Route::middleware('subscription:premium')
->prefix('teams')
->name('teams.')
->group(function () {
Route::apiResource('/', TeamController::class);
Route::post('/{team}/invite', [TeamController::class, 'invite'])
->name('invite');
});
});
// 公开接口(无需认证)
Route::prefix('v1/public')
->name('api.v1.public.')
->group(function () {
Route::get('/health', fn() => response()->json(['status' => 'ok']));
});

路由参数与约束

// 基础参数
Route::get('/tasks/{task}', [TaskController::class, 'show']);
// /tasks/42 → $task = 42(字符串)
// 类型约束
Route::get('/tasks/{task}', [TaskController::class, 'show'])
->whereNumber('task');  // 只匹配数字
Route::get('/users/{username}', [UserController::class, 'show'])
->whereAlpha('username');  // 只匹配字母
// 可选参数
Route::get('/archive/{year?}/{month?}', [ArchiveController::class, 'index']);
// 路由模型绑定(自动把 ID 解析成模型实例)
// 控制器方法参数名和路由参数名相同时自动绑定:
Route::get('/tasks/{task}', [TaskController::class, 'show']);
// TaskController.php:
public function show(Task $task) {
// $task 是已加载的 Task 模型,如果找不到自动 404
return new TaskResource($task);
}

自定义中间件

# 创建中间件
php artisan make:middleware EnsureTaskBelongsToUser
<?php
// app/Http/Middleware/EnsureTaskBelongsToUser.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class EnsureTaskBelongsToUser
{
public function handle(Request $request, Closure $next): mixed
{
$task = $request->route('task');
if ($task && $task->user_id !== auth()->id()) {
return response()->json(['error' => 'Forbidden'], 403);
}
return $next($request);  // 继续处理请求
}
}
// 在 bootstrap/app.php 注册中间件别名(Laravel 11)
->withMiddleware(function (Middleware $middleware) {
$middleware->alias([
'task.owner' => \App\Http\Middleware\EnsureTaskBelongsToUser::class,
]);
})
// 在路由中使用
Route::middleware(['auth:sanctum', 'task.owner'])
->group(function () {
Route::put('/tasks/{task}', [TaskController::class, 'update']);
Route::delete('/tasks/{task}', [TaskController::class, 'destroy']);
});

速率限制

// app/Providers/AppServiceProvider.php 中定义速率限制器
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;
public function boot(): void
{
// API 速率限制:每用户每分钟 60 次
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
// 登录限制:每 IP 每分钟 5 次尝试
RateLimiter::for('login', function (Request $request) {
return Limit::perMinute(5)->by($request->ip());
});
}
// 在路由中使用
Route::middleware('throttle:api')->group(function () {
// ...
});

routes/api.php 创建(Laravel 11 默认不存在)

# Laravel 11 默认没有 api.php,需要手动创建
php artisan install:api
# 这会:
# 1. 创建 routes/api.php
# 2. 在 bootstrap/app.php 中注册 api 路由
# 3. 安装 Laravel Sanctum(如果未安装)

调试路由

# 查看所有路由
php artisan route:list
# 过滤
php artisan route:list --path=api/v1/tasks
php artisan route:list --name=tasks
# 查看路由详情(中间件、控制器)
php artisan route:list -v

下一节Request 类与表单验证——Laravel 的 FormRequest 是控制器瘦身的关键:把验证逻辑从控制器方法中抽离,还能统一处理授权检查。