# 1、基本路由 >[info]大部分路由都定义在被App\Providers\RouteServiceProvider类载入的app/Http/routes.php文件中。 最基本的Laravel路由接收一个URI和一个闭包: ~~~ Route::get('/', function () { return 'Hello World'; }); Route::post('foo/bar', function () { return 'Hello World'; }); Route::put('foo/bar', function () { // }); Route::delete('foo/bar', function () { // }); ~~~ >[info]为多个动作注册路由有时候需要注册一个路由来响应多个不同的HTTP动作,你可以使用Route门面的match方法来实现: ~~~ Route::match(['get', 'post'], '/', function () { return 'Hello World'; }); 或者,还可以使用any方法注册一个路由响应所有HTTP动作: Route::any('foo', function () { return 'Hello World'; }); ~~~ >[info]生成路由对应的URLs 可以使用帮助函数url来生成路由对应的URLs: ~~~ $url = url('foo'); ~~~ # 2、路由参数 ## 2.1 必选参数 >[info]有时我们需要在路由中捕获URI片段,比如,如果想要从URL中捕获用户ID,可以通过如下方式定义路由参数: ~~~ Route::get('user/{id}', function ($id) { return 'User '.$id; }); ~~~ >[info]可以按需要定义在路由中定义多个路由参数: ~~~ Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) { // }); ~~~ >[info]路由参数总是通过花括号进行包裹,参数在路由被执行时会被传递到路由的闭包。 注意:路由参数不能包含’-‘字符,需要的话可以使用_替代。 ## 2.2 可选参数 >[info]有时候可能需要指定路由参数,并且使得该路由参数是可选的,可以通过在参数名后加一个?来标记: ~~~ Route::get('user/{name?}', function ($name = null) { return $name; }); Route::get('user/{name?}', function ($name = 'John') { return $name; }); ~~~ ## 2.3 正则约束 >[info]可以使用路由实例上的where方法来约束路由参数的格式。where方法接收参数名和一个正则表达式来定义该参数如何被约束: ~~~ Route::get('user/{name}', function ($name) { // })->where('name', '[A-Za-z]+'); Route::get('user/{id}', function ($id) { // })->where('id', '[0-9]+'); Route::get('user/{id}/{name}', function ($id, $name) { // })->where(['id' => '[0-9]+', 'name' => '[a-z]+']); ~~~ ### 2.3.1 全局约束 >[info]如果想要路由参数在全局范围内被给定正则表达式约束,可以使用pattern方法。可以在RouteServiceProvider类的boot方法中定义约束模式: ~~~ /** * 定义路由模型绑定,模式过滤器等 * * @param \Illuminate\Routing\Router $router * @return void * @translator http://laravelacademy.org */ public function boot(Router $router){ $router->pattern('id', '[0-9]+'); parent::boot($router); } ~~~ >[info]一旦模式被定义,将会自动应用到所有包含该参数名的路由中。 >[info]扩展阅读:实例教程——HTTP路由实例教程(一)—— 基本使用及路由参数 # 3、命名路由 >[info]命名路由使生成URLs或者重定向到指定路由变得很方便,在定义路由时指定路由名称,然后使用数组键as指定路由别名: ~~~ Route::get('user/profile', ['as' => 'profile', function () { // }]); 还可以为控制器动作指定路由名称: Route::get('user/profile', [ 'as' => 'profile', 'uses' => 'UserController@showProfile' ]); ~~~ ## 3.1 路由分组 & 命名路由 >[info]如果你在使用路由分组,可以在路由分组属性数组中指定as关键字来为分组中的路由设置一个共用的路由名前缀: ~~~ Route::group(['as' => 'admin::'], function () { Route::get('dashboard', ['as' => 'dashboard', function () { // 路由被命名为 "admin::dashboard" }]); }); ~~~ ## 3.2 为命名路由生成URLs >[info]一旦你为给定路由分配了名字,通过route函数生成URLs时就可以使用路由名字: ~~~ $url = route('profile'); $redirect = redirect()->route('profile'); ~~~ >[info]如果路由定义了参数,可以将路由参数作为第二个参数传递给route函数。给定的路由参数将会自动插入URL中: ~~~ Route::get('user/{id}/profile', ['as' => 'profile', function ($id) { // }]); $url = route('profile', ['id' => 1]); ~~~ # 4、路由分组 >[info]路由分组允许我们在多个路由中共享路由属性,比如中间件和命名空间等,这样的话一大波共享属性的路由就不必再各自定义这些属性。共享属性以数组的形式被作为第一个参数传递到Route::group方法中。 >[info]想要了解更多路由分组,我们希望通过几个简单的应用实例来展示其特性。 ## 4.1 中间件 >[info]要分配中间件给分组中的所有路由,可以在分组属性数组中使用middleware键。中间件将会按照数组中定义的顺序依次执行: ~~~ Route::group(['middleware' => 'auth'], function () { Route::get('/', function () { // 使用 Auth 中间件 }); Route::get('user/profile', function () { // 使用 Auth 中间件 }); }); ~~~ ## 4.2 命名空间 >[info]另一个通用的例子是路由分组分配同一个PHP命名空间给多个控制器,可以在分组属性数组中使用namespace参数来指定分组中控制器的命名空间: ~~~ Route::group(['namespace' => 'Admin'], function(){ // 控制器在 "App\Http\Controllers\Admin" 命名空间下 Route::group(['namespace' => 'User'], function() { // 控制器在 "App\Http\Controllers\Admin\User" 命名空间下 }); }); ~~~ >[info]默认情况下,RouteServiceProvider包含routes.php并指定其所在命名空间,因此,我们只需要指定命名空间的App\Http\Controllers之后的一部分。 ## 4.3 子域名路由 >[info]路由分组还可以被用于子域名路由通配符,子域名可以像URIs一样被分配给路由参数,从而允许捕获子域名的部分用于路由或者控制器,子域名可以通过分组属性数组中的domain键来指定: ~~~ Route::group(['domain' => '{account}.myapp.com'], function () { Route::get('user/{id}', function ($account, $id) { // }); }); ~~~ ## 4.4 路由前缀 >[info]属性prefix可以用来为分组中每个给定URI添加一个前缀,比如,你想要为所有路由URIs前面添加前缀admin: ~~~ Route::group(['prefix' => 'admin'], function () { Route::get('users', function () { // 匹配 "/admin/users" URL }); }); ~~~ >[info]你还可以使用prefix参数为分组路由指定公共参数: ~~~ Route::group(['prefix' => 'accounts/{account_id}'], function () { Route::get('detail', function ($account_id) { // 匹配 accounts/{account_id}/detail URL }); }); ~~~ >[info]扩展阅读:实例教程——HTTP路由实例教程(二)—— 路由命名和路由分组 # 5、防止CSRF攻击 ## 5.1 简介 >[info]Laravel使得防止应用遭到跨站请求伪造攻击变得简单。跨站请求伪造是一种通过伪装授权用户的请求来利用授信网站的恶意漏洞。 >[info]Laravel自动为每一个被应用管理的有效用户Session生成一个CSRF“令牌”,该令牌用于验证授权用户和发起请求者是否是同一个人。想要生成包含CSRF令牌的隐藏输入字段,可以使用帮助函数csrf_field来实现: ~~~ <?php echo csrf_field(); ?> 帮助函数csrf_field生成如下HTML: <input type="hidden" name="_token" value="<?php echo csrf_token(); ?>"> 当然还可以使用Blade模板引擎提供的方式: {!! csrf_field() !!} 你不需要了解在POST、PUT或者DELETE请求时CSRF令牌是如何进行验证的,HTTP中间件VerifyCsrfToken会为我们做这项工作:将请求中输入的token值和session中的存储的作对比。 ~~~