zoukankan      html  css  js  c++  java
  • HTTP层 —— 路由

     

    1、基本路由

    最基本的 Laravel 路由只接收一个 URI 和一个闭包,并以此提供一个非常简单且优雅的定义路由方法:

    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路由文件中所有请求方式为PUTPOSTDELETE的HTML表单都会包含一个CSRF令牌字段,否则,请求会被拒绝。关于CSRF的更多细节,可以参考其文档

    <form method="POST" action="/profile">
        {{ csrf_field() }}
        ...
    </form>
    
    2、路由参数
    必选参数

    有时我们需要在路由中捕获 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;
    });
    
    3、命名路由

    命名路由为生成 URL 或重定向提供了便利。实现也很简单,在路由定义之后使用 name 方法链的方式来实现:

    Route::get('user/profile', function () {
        //
    })->name('profile');
    

    还可以为控制器动作指定路由名称:

    Route::get('user/profile', 'UserController@showProfile')->name('profile');
    

    为命名路由生成URL

    为给定路由分配名称之后,就可以通过辅助函数 route 为该命名路由生成 URL:

    $url = route('profile');
    $redirect = redirect()->route('profile');
    

    如果命名路由定义了参数,可以将该参数作为第二个参数传递给 route 函数。给定的路由参数将会自动插入到 URL 中:

    Route::get('user/{id}/profile', ['as' => 'profile', function ($id) {
        //
    }]);
    $url = route('profile', ['id' => 1]);
    
    4、路由群组

    路由群组允许我们在多个路由中共享路由属性,比如中间件和命名空间等,这样的话我们就不必为每一个路由单独定义属性。共享属性以数组的形式作为第一个参数被传递给 Route::group 方法。

    中间件

    要给路由群组中定义的所有路由分配中间件,可以在群组属性数组中使用 middleware。中间件将会按照数组中定义的顺序依次执行:

    Route::group(['middleware' => 'auth'], function () {
        Route::get('/', function () {
            // 使用 Auth 中间件
        });
    
        Route::get('user/profile', function () {
            // 使用 Auth 中间件
        });
    });
    
    命名空间

    另一个通用的例子是路由群组分配同一个 PHP 命名空间给其下的多个控制器,可以在分组属性数组中使用 namespace来指定群组中所有控制器的公共命名空间:

    Route::group(['namespace' => 'Admin'], function(){
        // 控制器在 "AppHttpControllersAdmin" 命名空间下
    
        Route::group(['namespace' => 'User'], function(){
            // 控制器在 "AppHttpControllersAdminUser" 命名空间下
        });
    });
    

    默认情况下,RouteServiceProvider 引入你的路由文件并指定其下所有控制器类所在的默认命名空间AppHttpControllers,因此,我们在定义的时候只需要指定命名空间 AppHttpControllers 之后的部分即可。

    子域名路由

    路由群组还可以被用于子域名路由通配符,子域名可以像 URI 一样被分配给路由参数,从而允许捕获子域名的部分用于路由或者控制器,子域名可以通过群组属性数组中的 domain 来指定:

    Route::group(['domain' => '{account}.myapp.com'], function () {
        Route::get('user/{id}', function ($account, $id) {
            //
        });
    });
    
    路由前缀

    群组属性 prefix 可以用来为群组中每个路由添加一个给定 URI 前缀,例如,你可以为所有路由 URI 添加 admin 前缀 :

    Route::group(['prefix' => 'admin'], function () {
        Route::get('users', function () {
            // 匹配 "/admin/users" URL
        });
    });
    
    5、路由模型绑定

    注入模型ID到路由或控制器动作时,通常需要查询数据库才能获取相应的模型数据。Laravel 路由模型绑定让注入模型实例到路由变得简单,例如,你可以将匹配给定 ID 的整个 User 类实例注入到路由中,而不是直接注入用户 ID。

    隐式绑定

    Laravel 会自动解析定义在路由或控制器动作(变量名匹配路由片段)中的 Eloquent 模型类型声明,例如:

    Route::get('api/users/{user}', function (AppUser $user) {
        return $user->email;
    });
    

    在这个例子中,由于类型声明了 Eloquent 模型 AppUser,对应的变量名 $user 会匹配路由片段中的{user},这样,Laravel 会自动注入与请求 URI 中传入的 ID 对应的用户模型实例。

    如果数据库中找不到对应的模型实例,会自动生成 HTTP 404 响应。

    自定义键名

    如果你想要隐式模型绑定使用数据表的其它字段,可以重写 Eloquent 模型类的 getRouteKeyName 方法:

    /**
     * Get the route key for the model.
     *
     * @return string
     */
    public function getRouteKeyName()
    {
        return 'slug';
    }
    
    显式绑定

    要注册显式绑定,需要使用路由的 model 方法来为给定参数指定绑定类。应该在 RouteServiceProvider::boot 方法中定义模型绑定:

    绑定参数到模型

    public function boot()
    {
        parent::boot();
        $router->model('user', 'AppUser');
    }
    

    接下来,定义一个包含 {user} 参数的路由:

    $router->get('profile/{user}', function(AppUser $user) {
         //
    });
    

    由于我们已经绑定 {user} 参数到 AppUser 模型,User 实例会被注入到该路由。因此,如果请求 URL 是profile/1,就会注入一个用户 ID 为 1 的 User 实例。

    如果匹配的模型实例在数据库不存在,会自动生成并返回 HTTP 404 响应。

    自定义解析逻辑

    如果你想要使用自定义的解析逻辑,需要使用 Route::bind 方法,传递到 bind 方法的闭包会获取到 URI 请求参数中的值,并且返回你想要在该路由中注入的类实例:

    $router->bind('user', function($value) {
        return AppUser::where('name', $value)->first();
    });
    
    6、表单方法伪造

    HTML 表单不支持 PUTPATCH 或者 DELETE 请求方法,因此,当定义 PUTPATCHDELETE 路由时,需要添加一个隐藏的 _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_field('PUT') }}
    
    7、访问当前路由

    你可以使用 Route 门面上的 currentcurrentRouteNamecurrentRouteAction 方法来访问处理当前输入请求的路由信息:

    $route = Route::current();
    $name = Route::currentRouteName();
    $action = Route::currentRouteAction();
    

    参考API文档了解路由门面底层类以及Route实例的更多可用方法。

  • 相关阅读:
    【BZOJ 3090】 树形DP
    【BZOJ 2323】 2323: [ZJOI2011]细胞 (DP+矩阵乘法+快速幂*)
    【BZOJ 1019】 1019: [SHOI2008]汉诺塔 (DP?)
    【BZOJ 3294】 3294: [Cqoi2011]放棋子 (DP+组合数学+容斥原理)
    【BZOJ 3566】 3566: [SHOI2014]概率充电器 (概率树形DP)
    【BZOJ 2121】 (字符串DP,区间DP)
    【BZOJ 4305】 4305: 数列的GCD (数论)
    【UOJ 179】 #179. 线性规划 (单纯形法)
    【BZOJ 4568】 4568: [Scoi2016]幸运数字 (线性基+树链剖分+线段树)
    【BZOJ 4027】 4027: [HEOI2015]兔子与樱花 (贪心)
  • 原文地址:https://www.cnblogs.com/zhengyanbin2016/p/6005035.html
Copyright © 2011-2022 走看看