基础路由参数
这是最常见的参数类型,用于捕获 URL 中的特定部分。

(图片来源网络,侵删)
定义路由
在 routes/web.php 或 routes/api.php 文件中,使用大括号 来定义参数。
// routes/web.php
// 定义一个包含 id 参数的路由
Route::get('posts/{id}', function ($id) {
return "文章的 ID 是: " . $id;
});
// 定义一个包含 name 参数的路由
Route::get('users/{name}', function ($name) {
return "用户的名字是: " . $name;
});
访问示例:
- 访问
http://your-app.com/posts/123,会显示 "文章的 ID 是: 123"。 - 访问
http://your-app.com/users/tom,会显示 "用户的名字是: tom"。
如何在闭包中获取?
如上所示,Laravel 会自动将 URL 中的参数按顺序注入到路由闭包的函数参数中,你只需要在闭包的函数签名中定义一个同名变量即可。
Route::get('posts/{id}', function ($id) {
// $id 变量已经自动获取了 URL 中的值
return view('post.show', ['postId' => $id]);
});
可选路由参数
参数是可选的,你可以在参数名后面加上一个 来标记它为可选,必须在闭包中为该参数提供一个默认值。

(图片来源网络,侵删)
定义路由
// routes/web.php
// slug 参数是可选的
Route::get('posts/{id}/{slug?}', function ($id, $slug = null) {
if ($slug) {
return "文章 ID: {$id}, Slug: {$slug}";
}
return "只有文章 ID: {$id}";
});
访问示例:
- 访问
http://your-app.com/posts/123,会显示 "只有文章 ID: 123"。 - 访问
http://your-app.com/posts/123/my-first-post,会显示 "文章 ID: 123, Slug: my-first-post"。
正则约束路由参数
为了确保参数符合特定的格式(只能是数字),你可以使用 where 方法来为参数添加正则表达式约束。
定义路由
// routes/web.php
// 确保 id 参数只能是数字
Route::get('posts/{id}', function ($id) {
// ...
})->where('id', '[0-9]+');
// 可以同时为多个参数添加约束
Route::get('users/{id}/{name}', function ($id, $name) {
// ...
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
// 使用更简洁的闭包形式 (Laravel 7+)
Route::get('products/{category}', function ($category) {
// ...
})->where('category', fn ($category) => in_array($category, ['electronics', 'clothing']));
访问示例:
- 访问
http://your-app.com/posts/123(有效)。 - 访问
http://your-app.com/posts/abc(无效,会返回 404 错误)。
在控制器中获取路由参数
在实际项目中,我们通常使用控制器而不是闭包,获取参数的方式非常相似。

(图片来源网络,侵删)
定义路由
// routes/web.php
// 使用 @ 符号指定控制器和方法
Route::get('posts/{id}', 'PostController@show');
在控制器中获取
// app/Http/Controllers/PostController.php
namespace App\Http\Controllers;
use App\Models\Post; // 假设你有一个 Post 模型
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* 显示指定的文章
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
// 直接使用方法参数获取
$post = Post::find($id);
if (!$post) {
abort(404); // 如果找不到文章,返回 404
}
return view('post.show', ['post' => $post]);
}
}
高级:获取命名路由和路由模型绑定
这是 Laravel 更强大的功能,能让你的代码更优雅。
A. 获取命名路由的参数
给路由一个名字。
// routes/web.php
Route::get('posts/{id}', function ($id) {
// ...
})->name('posts.show');
然后在控制器或任何可以访问 route() 辅助函数的地方,通过 route() 函数的第二个参数传递参数。
// 在控制器中重定向
return redirect()->route('posts.show', ['id' => 123]);
// 或者生成 URL
$url = route('posts.show', ['id' => 123]);
如果参数名和路由参数名一致,可以简化写法:
// 如果控制器方法参数名是 $id,且路由参数名也是 id
public function show($id)
{
// ...
return redirect()->route('posts.show', $id); // Laravel 会自动匹配
}
B. 路由模型绑定
这是获取参数最“Laravel”的方式,它能自动将 URL 中的 ID 转换为对应的 Eloquent 模型实例。
隐式绑定
Laravel 会根据路由参数名(如 {post})自动查找控制器方法中同名的类型提示(如 Post $post)。
// routes/web.php
// 注意参数名是 {post}
Route::get('posts/{post}', 'PostController@show');
// app/Http/Controllers/PostController.php
use App\Models\Post;
class PostController extends Controller
{
// 方法参数 $post 会自动被注入 Post 模型实例
// 如果找不到 ID 对应的文章,会自动返回 404
public function show(Post $post)
{
// $post 已经是 App\Models\Post 的一个实例了!
// 不需要再写 Post::find($id);
return view('post.show', ['post' => $post]);
}
}
显式绑定
当你想使用自定义的逻辑或参数名与模型名不匹配时,可以使用显式绑定。
在 RouteServiceProvider 的 boot() 方法中定义:
// app/Providers/RouteServiceProvider.php
use Illuminate\Support\Facades\Route;
use App\Models\Post;
class RouteServiceProvider extends ServiceProvider
{
// ...
public function boot()
{
parent::boot();
// 将 'post' 参数绑定到 Post 模型
Route::model('post', Post::class);
// 或者使用闭包进行更复杂的绑定
// Route::bind('post', function ($value) {
// return Post::where('slug', $value)->firstOrFail();
// });
}
}
定义好绑定后,你的路由就可以这样写,控制器方法也能直接获得模型实例:
// routes/web.php
// 参数名是 {post},但绑定了 Post 模型
Route::get('posts/{post}', 'PostController@show');
// 控制器中的写法和隐式绑定完全一样
public function show(Post $post)
{
// ...
}
总结与最佳实践
| 场景 | 获取方式 | 示例 |
|---|---|---|
| 闭包路由 | 直接作为闭包函数的参数 | Route::get('/{id}', function($id) { ... }); |
| 控制器路由 | 直接作为控制器方法的参数 | Route::get('/{id}', 'PostController@show'); public function show($id) { ... } |
| 可选参数 | 参数名后加 ,闭包/控制器中提供默认值 | Route::get('/{id?}', function($id = null) { ... }); |
| 参数约束 | 使用 where() 方法添加正则表达式 |
Route::get('/{id}', ...)->where('id', '[0-9]+'); |
| 命名路由传参 | 使用 route() 辅助函数的第二个参数 |
return redirect()->route('name', ['id' => 1]); |
| 模型绑定 | 在控制器中使用类型提示获取模型实例 | Route::get('/posts/{post}', 'PostController@show'); public function show(Post $post) { ... } |
最佳实践建议:
- 优先使用控制器:保持
routes文件的整洁。 - 优先使用路由模型绑定:它能极大地简化你的控制器代码,避免手写
find()或firstOrFail(),代码更健壮、更易读。 - 为重要路由命名:使用
->name()为路由命名,这样在生成重定向或 URL 时就不需要硬编码路径,便于后期维护。 - 使用约束:对参数进行类型约束(如只能是数字)可以提前过滤无效请求,提高应用的鲁棒性。
