基本路由
Laravel 最基本的路由接收一个 URI 和一个 Closure
闭包,提供一个简单的、生动的方法定义路由:
Route::get('foo', function () { return 'Hello World'; });
默认路由文件
Laravel 所有的路由都定义在路由文件中,存放在 routes
目录中。这些文件会被框架自动加载。routes/web.php
文件为你的 WEB 接口定义路由。这些路由会被分配在 web
中间件组下,提供了 session 状态及 CSRF 保护等功能。routes/api.php
文件中的路由是无状态的,并被分配在 api
中间件组下。
对于大多数应用,路由都是定义在 routes/web.php
文件中。
可用的路由方法
路由允许你注册响应任何 HTTP 动词的路由:
Route::get($uri, $callback); Route::post($uri, $callback); Route::put($uri, $callback); Route::patch($uri, $callback); Route::delete($uri, $callback); Route::options($uri, $callback);
有时候你可能需要注册响应多个 HTTP 动词的路由,你可以使用 match
方法。或者你可以使用 any
方法注册一个响应所有 HTTP 动词的路由:
Route::match(['get', 'post'], '/', function () { // }); Route::any('foo', function () { // });
CSRF 保护
任何定义在 web
路由文件中的指向 POST
、PUT
或 DELETE
路由的 HTML 表单,都应当包含一个 CSRF token 字段。否则,请求将会被拒绝。你可以在 CSRF 文档中了解更多关于 CSRF 保护的内容:
<form method="POST" action="/profile"> {{ csrf_field() }} ... </form>
路由参数
基础路由参数
有时候你可能需要从你的 URI 路由中来获取一些参数。例如,你需要从 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; }); Route::get('user/{name?}', function ($name = 'John') { return $name; });
命名路由
命名路由让你可以更方便的为特定路由生成 URL 或进行重定向。你可以在路由定义后链式调用 name
方法为路由指定名称:
Route::get('user/profile', function () { // })->name('profile');
你也可以为控制器方法路由指定参数:
Route::get('user/profile', 'UserController@showProfile')->name('profile');
为命名路由生成 URLs
一旦你为一个给定的路由指定了名称,当生成 URLs 的时候你可以使用路由名称或使用全局的 route
方法:
// Generating URLs... $url = route('profile'); // Generating Redirects... return redirect()->route('profile');
如果命名路由定义了参数,你可以把参数作为第二个参数传递给 route
函数。指定的参数将自动添加到 URL 的正确位置上:
Route::get('user/{id}/profile', function ($id) { // })->name('profile'); $url = route('profile', ['id' => 1]);
路由组
路由组允许你在多个路由中分享路由参数,例如中间件或命名空间,而不需要在每个路由中单独定义这些参数。分享的路由参数会以数组的形式作为第一个参数传递给 Route::group
方法。
中间件
要为一组路由指定中间件,需要在组属性数组中使用 middleware
键。中间件将会依照列表内指定的顺序运行:
Route::group(['middleware' => 'auth'], function () { Route::get('/', function () { // Uses Auth Middleware }); Route::get('user/profile', function () { // Uses Auth Middleware }); });
命名空间
另一个常用的情况是为一组控制器指定相同的 PHP 命名空间,通过在 group
数组中使用 namespace
参数来实现:
Route::group(['namespace' => 'Admin'], function() { // Controllers Within The "App\Http\Controllers\Admin" Namespace });
记住,默认情况下,RouteServiceProvider
会把你的路由文件包含在一个命名空间组内,允许你在不需要指定全部 App\Http\Controllers
命名空间前缀就可以注册路由。所以,你只需指定位于 App\Http\Controllers
之后的一部分命名空间即可。
子域名路由
路由组还可以用来处理子域名路由。子域名可以像路由 URI 那样通过路由参数来指定,让你捕获子域名的部分以便在路由或控制器中使用。子域名可以通过在组属性数组中设置 domain
键来指定。
Route::group(['domain' => '{account}.myapp.com'], function () { Route::get('user/{id}', function ($account, $id) { // }); });
路由前缀
prefix
组属性可以用来为组中每一个路由加上一个给定的 URI 前缀。例如,你想为组中所有路由加上 admin
前缀:
Route::group(['prefix' => 'admin'], function () { Route::get('users', function () { // Matches The "/admin/users" URL }); });
路由模型绑定
当注入一个模型 ID 到路由或控制器方法时,你经常会需要取回对应 ID 的模型。Laravel 路由模型绑定提供了一中方便的方式自动注入模型实例到你的路由。例如,你可以将匹配给定 ID 的整个 User
类实例注入到路由中,而不是直接注入用户 ID。
隐式绑定
Laravel 会自动解析定义在路由或控制器方法中与路由片段匹配的 Eloquent 模型类型声明,例如:
Route::get('api/users/{user}', function (App\User $user) { return $user->email; });
在这个例子中,由于 Eloquent 中定义的 $user
变量与路由 URI 中的 {user}
相匹配,Laravel 会自动注入与请求 URI 中与 ID 的值相应的模型实例。如果匹配的模型实例在数据库中没找到,则会自动生成一个 404 状态的 HTTP 响应。
自定义键名
当要获取一个给定的模型时,如果你想隐式绑定使用 ID 以外的数据库字段,那么你可以在 Eloquent 模型中重写 getRouteKeyName
方法:
/** * 获取模型的路由键值 * * @return string */ public function getRouteKeyName() { return 'slug'; }
显式绑定
要注册显式绑定,请使用路由的 model
方法来指定给定参数的类名。你需要在 RouteServiceProvider
类的 boot
方法中来定义你的显式模型绑定:
public function boot() { parent::boot(); Route::model('user', 'App\User'); }
然后定义一个包含 {user}
参数的路由:
$router->get('profile/{user}', function(App\User $user) { // });
由于我们已经把 {user}
参数与 App\User
模型绑定到了一起,因此 User
实例将会被注入到路由中。例如,profile/1
请求将会把数据库中 ID 为 1 的 User
实例注入到路由。
如果匹配的模型实例在数据库中没找到,则会自动生成一个 404 状态的 HTTP 响应。
自定义解析逻辑
如果你想使用自己的解析逻辑,你可以使用 Route::bind
方法。你传递给 bind
方法的匿名函数将接收 URI 参数的值,并返回需要注入到路由中的类的实例。
表单方法欺骗
HTML 表单不支持 PUT
、PATCH
、DELETE
方法。所以,当定义需要在 HTML 表单中调用的 PUT
、PATCH
、DELETE
路由时,你需要为表单添加一个 _method 隐藏域。_method
的值将会被用作 HTTP 请求的方法:
<form action="/foo/bar" method="POST"> <input type="hidden" name="_method" value="PUT"> <input type="hidden" name="_token" value="{{ csrf_token() }}"> </form>
你可以使用 method_field
方法来生成 _method
隐藏域:
{{ method_field('PUT') }}
访问当前路由
你可以在 Route Facade上使用 current
、currentRouteName
、以及 currentRouteAction
方法来得到当前进入请求的信息:
$route = Route::current(); $name = Route::currentRouteName(); $action = Route::currentRouteAction();
参考 Route facade 的底层类以及 Route 实例的 API 文档来获取更多信息。
该篇属于专题:《Laravel 5.3 中文文档》
public 2016/08/31 09:41
感谢楼主,5.3中为何不见路由正则?不支持了吗?另在5.3中使用5.2中的Global Constraints 报错Declaration of App\Providers\RouteServiceProvider::boot(Illuminate\Routing\Router $router) should be compatible with Illuminate\Foundation\Support\Providers\RouteServiceProvider::boot()求解释
Specs 2016/08/31 21:35
@ Illuminate\Routing\Router 这个改成 Facade, 用 use Route 试试。参考自 laracasts.com/discuss/channels/laravel/l53-routeserviceprovider-update