在 Laravel 中一个典型的路由定义是这样的:
routes/web.php
// 闭包方式定义路由
Route::get('foo', function () {
return 'Hello World';
})
当然也可以将其指定到具体控制器:
Route::get('home', 'PagesController@home');
routes/web.php 文件用于定义 web 界面的路由。里面的路由都会被分配给 web 中间件组,它提供了会话状态和 CSRF 保护等功能。定义在 routes/api.php 中的路由都是无状态的,并且被分配了 api 中间件组。
当然,有时需要在路由中捕获一些 URL 片段。例如,从 URL 中捕获用户的 ID,可以通过定义路由参数来执行此操作:
Route::get('user/{id}', function ($id) {
return 'User ' . $id;
})
也可以根据需要在路由中定义多个参数:
Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
//
})
路由的参数通常都会被放在 {}
内,并且参数名只能为字母,同时路由参数不能包含 -
符号,如果需要可以用下划线 _
代替。路由参数会按顺序依次被注入到路由回调或者控制器中,而不受回调或者控制器的参数名称的影响。
有时,可能需要指定一个路由参数,但希望这个参数是可选的。那么可以在参数后面加上 ?
标记来实现,但前提是要确保路由的相应变量有默认值:
Route::get('user/{name?}', function ($name = null) {
return $name;
})
当向路由或控制器行为注入模型 ID 时,就需要查询这个 ID 对应的模型。Laravel 为路由模型绑定提供了一个自动将模型实例注入到路由中的方法。例如,你可以注入与给定 ID 匹配的整个 User 模型实例,而不是仅注入用户的 ID。
Route::get('api/users/{user}', function (User $user) {
return $user->email;
})
实现路由模型的自动绑定,需要满足以下条件:
控制器或闭包中的变量「类型提示」或「类型约束」为 Eloquent 模型
控制器或闭包中的变量名与路由中的变量名匹配
满足以上两个条件即可实现路由模型的自动注入。该功能是由中间件的 \Illuminate\Routing\Middleware\SubstituteBindings
类来完成的。该中间件同时存在于 web 和 api 中间件组中。
除了自动绑定,还可以进行显式绑定。要注册显式绑定,使用路由器的 model()
方法来为给定参数指定要绑定的类。在 RouteServiceProvider
类中的 boot()
方法内定义显式模型绑定:
app/Providers/RouteServiceProvider.php
public function boot()
{
parent::boot();
Route::model('user', App\Models\User::class);
}
接着,定义一个包含 {user}
参数的路由:
routes/web.php
Route::get('profile/{user}', function (User $user) {
//
})
因为我们已经将所有 {user}
参数绑定到 App\Models\User
模型,所有 User 实例将被注入到该路由。例如,profile/1
的请求会注入数据库中 ID 为 1 的 User 实例。
如果在数据库中不存在对应 ID 的数据,就会自动抛出一个 404 异常。
路由参数会按顺序依次被注入到路由回调或者控制器中,而不受回调或者控制器的参数名称的影响。
要实现路由模型自动绑定,满足以下要求:
控制器或闭包中的变量「类型提示」或「类型约束」为 Eloquent 模型
控制器或闭包中的变量名与路由中的变量名匹配