Laravel 路由系统完全指南:从基础到高级应用
Orion K Lv6

Laravel 的路由系统是框架的核心组件之一,它负责将 HTTP 请求映射到相应的控制器或闭包函数。本文将深入探讨 Laravel 路由系统的各个方面,从基础用法到高级特性。

基础路由概念

路由文件结构

Laravel 中的所有路由都定义在 routes 目录中:

  • routes/web.php - 用于 Web 界面的路由,自动应用 web 中间件组
  • routes/api.php - 用于 API 路由,自动应用 api 中间件组和 /api 前缀
  • routes/console.php - 用于 Artisan 命令
  • routes/channels.php - 用于广播频道

基本路由定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 基本 GET 路由
Route::get('/users', function () {
return 'Hello World';
});

// 使用控制器
use App\Http\Controllers\UserController;
Route::get('/users', [UserController::class, 'index']);

// 支持多种 HTTP 方法
Route::post('/users', [UserController::class, 'store']);
Route::put('/users/{id}', [UserController::class, 'update']);
Route::delete('/users/{id}', [UserController::class, 'destroy']);

// 响应多个 HTTP 方法
Route::match(['get', 'post'], '/contact', function () {
// 处理 GET 和 POST 请求
});

// 响应所有 HTTP 方法
Route::any('/search', function () {
// 处理所有 HTTP 方法
});

路由参数

必需参数

1
2
3
4
5
6
7
8
9
// 单个参数
Route::get('/user/{id}', function ($id) {
return 'User ID: ' . $id;
});

// 多个参数
Route::get('/posts/{post}/comments/{comment}', function ($postId, $commentId) {
return "Post: {$postId}, Comment: {$commentId}";
});

可选参数

1
2
3
4
// 可选参数需要提供默认值
Route::get('/user/{name?}', function ($name = 'Guest') {
return 'Hello ' . $name;
});

正则表达式约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 参数必须是数字
Route::get('/user/{id}', function ($id) {
return 'User ID: ' . $id;
})->where('id', '[0-9]+');

// 参数必须是字母
Route::get('/user/{name}', function ($name) {
return 'User Name: ' . $name;
})->where('name', '[A-Za-z]+');

// 多个约束
Route::get('/user/{id}/{name}', function ($id, $name) {
return "User: {$id} - {$name}";
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

// 全局约束(在 RouteServiceProvider 中定义)
public function boot()
{
Route::pattern('id', '[0-9]+');
parent::boot();
}

命名路由

命名路由允许为特定路由生成 URL 或重定向:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 定义命名路由
Route::get('/user/profile', [UserController::class, 'profile'])->name('user.profile');

// 在控制器中使用
public function redirectToProfile()
{
return redirect()->route('user.profile');
}

// 在视图中使用
<a href="{{ route('user.profile') }}">用户资料</a>

// 带参数的命名路由
Route::get('/user/{id}', [UserController::class, 'show'])->name('user.show');

// 生成带参数的 URL
$url = route('user.show', ['id' => 1]);
// 或者
$url = route('user.show', 1);

路由组

路由组允许在多个路由之间共享属性:

中间件组

1
2
3
4
5
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::get('/profile', [ProfileController::class, 'show']);
Route::post('/profile', [ProfileController::class, 'update']);
});

路由前缀

1
2
3
4
Route::prefix('admin')->group(function () {
Route::get('/users', [AdminController::class, 'users']); // /admin/users
Route::get('/posts', [AdminController::class, 'posts']); // /admin/posts
});

子域名路由

1
2
3
4
5
Route::domain('{account}.example.com')->group(function () {
Route::get('/user/{id}', function ($account, $id) {
return "Account: {$account}, User: {$id}";
});
});

命名空间和名称前缀

1
2
3
4
5
6
7
Route::name('admin.')
->prefix('admin')
->middleware('auth')
->group(function () {
Route::get('/users', [AdminController::class, 'users'])->name('users'); // admin.users
Route::get('/posts', [AdminController::class, 'posts'])->name('posts'); // admin.posts
});

中间件

路由中间件

1
2
3
4
5
6
7
8
9
10
// 单个中间件
Route::get('/profile', [ProfileController::class, 'show'])->middleware('auth');

// 多个中间件
Route::get('/admin', [AdminController::class, 'index'])
->middleware(['auth', 'admin']);

// 中间件参数
Route::get('/posts/{post}', [PostController::class, 'show'])
->middleware('throttle:60,1');

中间件组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 在 app/Http/Kernel.php 中定义中间件组
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];

资源路由

资源路由为 RESTful 控制器提供便捷的路由定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 完整的资源路由
Route::resource('posts', PostController::class);

// 等同于以下路由:
// GET /posts - index
// GET /posts/create - create
// POST /posts - store
// GET /posts/{post} - show
// GET /posts/{post}/edit - edit
// PUT/PATCH /posts/{post} - update
// DELETE /posts/{post} - destroy

// 部分资源路由
Route::resource('posts', PostController::class)->only(['index', 'show']);
Route::resource('posts', PostController::class)->except(['create', 'edit']);

// API 资源路由(排除 create 和 edit)
Route::apiResource('posts', PostController::class);

// 嵌套资源
Route::resource('posts.comments', CommentController::class);

模型绑定

隐式绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 路由定义
Route::get('/users/{user}', [UserController::class, 'show']);

// 控制器方法
public function show(User $user)
{
// Laravel 自动根据 ID 查找用户
return view('user.profile', compact('user'));
}

// 自定义键名
Route::get('/users/{user:slug}', [UserController::class, 'show']);

// 在模型中定义默认路由键
public function getRouteKeyName()
{
return 'slug';
}

显式绑定

1
2
3
4
5
6
7
8
9
10
11
12
// 在 RouteServiceProvider 的 boot 方法中
public function boot()
{
Route::model('user', User::class);

// 或者自定义解析逻辑
Route::bind('user', function ($value) {
return User::where('name', $value)->firstOrFail();
});

parent::boot();
}

高级路由特性

回退路由

1
2
3
4
// 当没有其他路由匹配时执行
Route::fallback(function () {
return view('errors.404');
});

速率限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 基本速率限制
Route::middleware('throttle:60,1')->group(function () {
Route::get('/api/users', [UserController::class, 'index']);
});

// 动态速率限制
Route::middleware('throttle:rate_limit,1')->group(function () {
Route::get('/api/users', [UserController::class, 'index']);
});

// 在用户模型中定义
public function rate_limit()
{
return $this->is_premium ? 1000 : 60;
}

表单方法伪造

1
2
3
4
5
6
<!-- HTML 表单只支持 GET 和 POST,使用 @method 指令伪造其他方法 -->
<form action="/posts/1" method="POST">
@csrf
@method('PUT')
<!-- 表单字段 -->
</form>

路由缓存

1
2
3
4
5
6
7
8
# 缓存路由以提高性能
php artisan route:cache

# 清除路由缓存
php artisan route:clear

# 查看所有路由
php artisan route:list

实际应用示例

API 路由设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// routes/api.php
Route::prefix('v1')->group(function () {
// 公开路由
Route::post('/login', [AuthController::class, 'login']);
Route::post('/register', [AuthController::class, 'register']);

// 需要认证的路由
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', [AuthController::class, 'user']);
Route::post('/logout', [AuthController::class, 'logout']);

// 用户资源
Route::apiResource('users', UserController::class);

// 文章资源
Route::apiResource('posts', PostController::class);
Route::apiResource('posts.comments', CommentController::class);
});

// 管理员路由
Route::middleware(['auth:sanctum', 'admin'])->prefix('admin')->group(function () {
Route::get('/dashboard', [AdminController::class, 'dashboard']);
Route::apiResource('users', AdminUserController::class);
});
});

Web 路由设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// routes/web.php
Route::get('/', [HomeController::class, 'index'])->name('home');

// 认证路由
Auth::routes();

// 需要认证的路由
Route::middleware('auth')->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');

// 用户资料
Route::prefix('profile')->name('profile.')->group(function () {
Route::get('/', [ProfileController::class, 'show'])->name('show');
Route::get('/edit', [ProfileController::class, 'edit'])->name('edit');
Route::put('/', [ProfileController::class, 'update'])->name('update');
});

// 文章管理
Route::resource('posts', PostController::class);
});

// 管理员路由
Route::middleware(['auth', 'admin'])->prefix('admin')->name('admin.')->group(function () {
Route::get('/', [AdminController::class, 'index'])->name('index');
Route::resource('users', AdminUserController::class);
Route::resource('posts', AdminPostController::class);
});

性能优化建议

  1. 使用路由缓存:在生产环境中使用 php artisan route:cache
  2. 合理使用路由组:减少重复的中间件和前缀定义
  3. 避免过度嵌套:保持路由结构清晰简洁
  4. 使用资源路由:遵循 RESTful 设计原则
  5. 合理使用模型绑定:减少手动查询数据库的代码

总结

Laravel 的路由系统提供了强大而灵活的请求处理机制。通过合理使用路由参数、中间件、路由组和模型绑定等特性,可以构建出结构清晰、易于维护的 Web 应用程序。掌握这些路由技巧将大大提高你的 Laravel 开发效率。

本站由 提供部署服务