路由参数 #

一、必选参数 #

1.1 基本用法 #

php
use Illuminate\Support\Facades\Route;

Route::get('/users/{id}', function ($id) {
    return "用户ID: {$id}";
});

1.2 多个参数 #

php
Route::get('/posts/{postId}/comments/{commentId}', function ($postId, $commentId) {
    return "文章 {$postId} 的评论 {$commentId}";
});

1.3 参数命名规范 #

php
// 推荐:使用有意义的参数名
Route::get('/users/{user}', function ($user) {
    return $user;
});

// 不推荐:使用无意义的名称
Route::get('/users/{id}', function ($id) {
    return $id;
});

1.4 参数顺序 #

参数顺序必须与URL中的顺序一致:

php
// 正确
Route::get('/users/{userId}/posts/{postId}', function ($userId, $postId) {
    return "用户 {$userId} 的文章 {$postId}";
});

// 错误:参数顺序不匹配
Route::get('/users/{userId}/posts/{postId}', function ($postId, $userId) {
    // $postId 实际是 userId 的值
});

二、可选参数 #

2.1 基本用法 #

php
Route::get('/users/{id?}', function ($id = null) {
    if ($id) {
        return "用户ID: {$id}";
    }
    return '所有用户';
});

2.2 默认值 #

php
Route::get('/users/{name?}', function ($name = 'Guest') {
    return "欢迎, {$name}!";
});

2.3 可选参数位置 #

可选参数必须放在路由末尾:

php
// 正确
Route::get('/posts/{id}/{slug?}', function ($id, $slug = null) {
    return "文章 {$id}";
});

// 错误:可选参数不能在必选参数前面
Route::get('/posts/{slug?}/{id}', function ($slug = null, $id) {
    // 这会导致错误
});

三、参数约束 #

3.1 where方法 #

使用正则表达式约束参数:

php
// 约束为数字
Route::get('/users/{id}', function ($id) {
    return "用户ID: {$id}";
})->where('id', '[0-9]+');

// 约束为字母
Route::get('/users/{name}', function ($name) {
    return "用户名: {$name}";
})->where('name', '[a-zA-Z]+');

// 约束为字母和数字
Route::get('/posts/{slug}', function ($slug) {
    return "文章别名: {$slug}";
})->where('slug', '[a-zA-Z0-9\-]+');

3.2 多个约束 #

php
Route::get('/posts/{id}/{slug}', function ($id, $slug) {
    return "文章 {$id}: {$slug}";
})->where([
    'id' => '[0-9]+',
    'slug' => '[a-zA-Z0-9\-]+'
]);

3.3 常用约束正则 #

约束类型 正则表达式 说明
数字 [0-9]+\d+ 只匹配数字
字母 [a-zA-Z]+ 只匹配字母
字母数字 [a-zA-Z0-9]+ 匹配字母和数字
Slug [a-zA-Z0-9\-_]+ URL友好的字符串
UUID [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} UUID格式

3.4 约束助手方法 #

Laravel提供了便捷的约束方法:

php
// 数字约束
Route::get('/users/{id}', function ($id) {
    return $id;
})->whereNumber('id');

// 字母约束
Route::get('/users/{name}', function ($name) {
    return $name;
})->whereAlpha('name');

// 字母数字约束
Route::get('/users/{username}', function ($username) {
    return $username;
})->whereAlphaNumeric('username');

// UUID约束
Route::get('/users/{uuid}', function ($uuid) {
    return $uuid;
})->whereUuid('uuid');

// ULID约束
Route::get('/posts/{ulid}', function ($ulid) {
    return $ulid;
})->whereUlid('ulid');

3.5 全局约束 #

RouteServiceProvider 中定义全局约束:

php
// app/Providers/RouteServiceProvider.php

public function boot()
{
    // 所有 {id} 参数必须是数字
    Route::pattern('id', '[0-9]+');
    
    // 所有 {slug} 参数必须是字母数字
    Route::pattern('slug', '[a-z0-9-]+');
    
    parent::boot();
}

四、参数编码 #

4.1 编码斜杠 #

默认情况下,参数中不能包含斜杠:

php
// 默认不支持
// /search/category/subcategory
Route::get('/search/{query}', function ($query) {
    return $query;
});

允许斜杠:

php
Route::get('/search/{query}', function ($query) {
    return $query;
})->where('query', '.*');

4.2 编码特殊字符 #

php
// 空格会被编码为 %20
Route::get('/search/{keyword}', function ($keyword) {
    return "搜索: {$keyword}";
});

// 访问 /search/hello%20world
// $keyword = "hello world"

五、访问路由参数 #

5.1 在闭包中访问 #

php
Route::get('/users/{id}', function ($id) {
    return $id;
});

5.2 在控制器中访问 #

php
// 控制器方法自动注入参数
class UserController extends Controller
{
    public function show($id)
    {
        return "用户ID: {$id}";
    }
}

5.3 通过Request对象访问 #

php
use Illuminate\Http\Request;

Route::get('/users/{id}', function (Request $request) {
    $id = $request->route('id');
    return $id;
});

// 获取所有参数
Route::get('/posts/{postId}/comments/{commentId}', function (Request $request) {
    $params = $request->route()->parameters();
    // ['postId' => 1, 'commentId' => 2]
});

5.4 在中间件中访问 #

php
// app/Http/Middleware/CheckPostOwner.php
public function handle($request, Closure $next)
{
    $postId = $request->route('post');
    
    // 检查权限
    
    return $next($request);
}

六、高级用法 #

6.1 参数默认值 #

php
Route::get('/category/{category?}', function ($category = 'all') {
    return "分类: {$category}";
});

6.2 参数转换 #

php
Route::get('/users/{id}', function ($id) {
    // 强制类型转换
    $id = (int) $id;
    return $id;
});

6.3 参数验证 #

php
Route::get('/users/{id}', function ($id) {
    if (!is_numeric($id) || $id <= 0) {
        abort(404);
    }
    return "用户ID: {$id}";
});

七、路由参数与模型绑定 #

7.1 隐式绑定 #

php
use App\Models\User;

Route::get('/users/{user}', function (User $user) {
    return $user;
});

// 访问 /users/1
// 自动查询 id=1 的用户

7.2 自定义键名 #

php
Route::get('/users/{user:slug}', function (User $user) {
    return $user;
});

// 访问 /users/john
// 自动查询 slug='john' 的用户

7.3 显式绑定 #

php
// RouteServiceProvider 中定义
public function boot()
{
    parent::boot();
    
    Route::model('user', User::class);
}

// 路由中使用
Route::get('/users/{user}', function (User $user) {
    return $user;
});

八、参数与URL生成 #

8.1 生成带参数的URL #

php
Route::get('/users/{id}', function ($id) {
    return $id;
})->name('users.show');

// 生成URL
$url = route('users.show', ['id' => 1]);
// http://example.com/users/1

8.2 多个参数 #

php
Route::get('/posts/{postId}/comments/{commentId}', function ($postId, $commentId) {
    return [$postId, $commentId];
})->name('comments.show');

$url = route('comments.show', ['postId' => 1, 'commentId' => 5]);
// http://example.com/posts/1/comments/5

8.3 额外查询参数 #

php
$url = route('users.show', ['id' => 1, 'tab' => 'profile']);
// http://example.com/users/1?tab=profile

九、参数约束最佳实践 #

9.1 使用语义化约束 #

php
// 好的做法
Route::get('/users/{id}', function ($id) {
    return $id;
})->whereNumber('id');

// 避免
Route::get('/users/{id}', function ($id) {
    return $id;
})->where('id', '[0-9]+');

9.2 约束复用 #

php
// 定义公共约束
Route::pattern('id', '[0-9]+');
Route::pattern('slug', '[a-z0-9-]+');

// 自动应用
Route::get('/users/{id}', function ($id) {
    return $id;
});

Route::get('/posts/{slug}', function ($slug) {
    return $slug;
});

9.3 约束与验证分离 #

php
// 路由约束:确保格式正确
Route::get('/users/{id}', function ($id) {
    return $id;
})->whereNumber('id');

// 控制器验证:确保业务逻辑正确
public function show($id)
{
    $user = User::findOrFail($id);
    return view('users.show', compact('user'));
}

十、常见问题 #

10.1 参数匹配顺序 #

php
// 正确:更具体的路由在前
Route::get('/users/create', function () {
    return '创建用户表单';
});

Route::get('/users/{id}', function ($id) {
    return "用户ID: {$id}";
});

// 错误:顺序颠倒会导致 /users/create 匹配到 {id}

10.2 可选参数与默认值 #

php
// 正确
Route::get('/users/{status?}', function ($status = 'active') {
    return $status;
});

// 访问 /users -> active
// 访问 /users/inactive -> inactive

10.3 参数命名冲突 #

php
// 避免:同名参数在不同路由中含义不同
Route::get('/users/{id}', ...);  // 用户ID
Route::get('/posts/{id}', ...);  // 文章ID

// 推荐:使用语义化命名
Route::get('/users/{userId}', ...);
Route::get('/posts/{postId}', ...);

十一、总结 #

11.1 核心要点 #

要点 说明
必选参数 {param} 格式
可选参数 {param?} 格式,需默认值
参数约束 where() 方法或全局 pattern()
约束助手 whereNumber, whereAlpha
模型绑定 自动解析模型实例

11.2 下一步 #

掌握了路由参数后,让我们继续学习 路由组与中间件,了解如何组织复杂路由!

最后更新:2026-03-28