Second, the basic components - Middleware

Brief introduction

   Middleware to filter HTTP requests into the application provides a convenient mechanism. For example, Laravel a built-in middleware to verify whether the user is authenticated (such as login), if the user is not authenticated, middleware redirects the user to the login page if the user has been authenticated, the middleware will allow the request to continue advances to the next step.

   Of course, in addition to authentication, the middleware may also be used to handle many other tasks. For example: CORS middleware may be used to add appropriate header (cross-domain) in response to leaving the site; middleware log records all requests go to the site so as to facilitate the system we build the system log.

   Laravel framework comes with a number of middleware, including certification, CSRF protection middleware and so on. All middleware are located in  app/Http/Middleware the directory.

The definition of middleware

   To create a new middleware, through Artisan command make:middleware

php artisan make:middleware CheckToken

   This command will  app/Http/Middleware create a new middleware classes directory  CheckToken, in this middleware, we are only allowed to offer  token equal to the specified value requesting access route tlar.com, otherwise, we will jump to Baidu:

    

   If  token != 'tlar.com', middleware returns an HTTP redirect to Baidu; otherwise, the request will be passed on. The request is passed down by calling the callback function  $next and pass the current  $request.

   Note: This is just a good definition of logic middleware middleware to make this into effect, but also to register to the specified route

   The best way is to be understood that the middleware will be seen as HTTP requests arrive middleware "layer" must pass before a certain action, each layer will check request and may completely reject it.

   Note: All middle are resolved in the service container, so you can rely on any type of prompt in the constructor's middleware.

   Request before / after middleware

     Middleware is a request before or after the request execution depends on the middleware itself.

     For example, the following middleware performs a number of tasks before the request processing:

 <?php

   namespace App\Http\Middleware;

   use Closure;

   class BeforeMiddleware
  {
      public function handle($request, Closure $next)
      {
         // 执行动作
         return $next($request);
      }
  }

     The following middleware will carry out its tasks after the request processing:

 <?php

   namespace App\Http\Middleware;

   use Closure;

   class AfterMiddleware
  {
      public function handle($request, Closure $next)
      {
         $response = $next($request);

         // 执行动作

         return $response;
      }
  }

Registration Middleware

   Three intermediate points are global intermediate member, and a routing group middleware:

   Global Middleware

     If you want to define middleware are executed at the time of each HTTP request, just to add to the corresponding middleware class  app/Http/Kernel.phparray of property  $middleware in the can:

      

     Unless really necessary, or generally not put into a global business-level middleware middleware.

   Middleware assigned to a specific route

     如果你想要分配中间件到指定路由,首先应该在 app/Http/Kernel.php 文件中分配给该中间件一个 key,默认情况下,该类的 $routeMiddleware 属性包含了 Laravel 自带的中间件,要添加你自己的中间件,只需要将其追加到后面并为其分配一个 key,例如:

    

     中间件在 HTTP Kernel 中被定义后,可以使用 middleware 方法将其分配到路由:

  Route::get('/', function () {
      return 'token';
  })->middleware('token');

中间件组

   有时候你可能想要通过指定一个键名的方式将相关中间件分到同一个组里面,这样可以更方便地将其分配到路由中,这可以通过使用 HTTP Kernel 提供的 $middlewareGroups 属性实现。

   Laravel 自带了开箱即用的 web 和 api 两个中间件组,分别包含可以应用到 Web 和 API 路由的通用中间件:

   

     中间件组使用和分配单个中间件同样的语法被分配给路由和控制器动作。再次申明,中间件组的目的只是让一次分配给路由多个中间件的实现更加方便:

Route::get('/', function () {
    //
})->middleware('web');

Route::group(['middleware' => ['web']], function () {
    //
});

     默认情况下, RouteServiceProvider 自动将中间件组 web 应用到 routes/web.php 文件,将中间件组 api 应用到 routes/api.php

   

     当然可以自己设置自己的中间件组,以实现更灵活的中间件分配策略:

/**
 * 应用的中间件组.
 *
 * @var array
 */
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        'throttle:60,1',
        'auth:api',
    ],
    #新增blog
    'blog' => [
        'token',
    ]
];

     修改 routes/web.php 下面的中间件分配方式:

Route::group(['middleware'=>['blog']],function(){
    Route::get('/', function () {
        return view('welcome', ['name' => 'blog view']);
    });

    Route::view('/view', 'welcome', ['website' => 'blog /view ']);
});

     这样访问 http://blog.tlar 和 http://blog.tlar/view 的时候都要带上 token=tlar.com 参数,否则就会跳转到百度。

中间件排序

     在某些特殊场景下,你可能需要中间件按照特定顺序执行,但是一旦中间件已经分配到指定路由就没法控制它们的执行顺序了。

     在这种情况下,你可以在 app/Http/Kernel.php 文件中通过 $middlewarePriority 属性来指定中间件的优先级:

/**
 * The priority-sorted list of middleware.
 *
 * This forces non-global middleware to always be in the given order.
 *
 * @var array
 */
protected $middlewarePriority = [
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \App\Http\Middleware\Authenticate::class,
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,
];

中间件参数

     中间件还可以接收额外的自定义参数,例如,如果应用需要在执行给定动作之前验证认证用户是否拥有指定的角色,可以创建一个 CheckRole 来接收角色名作为额外参数。

     额外的中间件参数会在 $next 参数之后传入中间件:

<?php

namespace App\Http\Middleware;

use Closure;

class CheckRole
{
    /**
     * 处理输入请求
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure $next
     * @param string $role
     * @return mixed
     * translator http://laravelacademy.org
     */
    public function handle($request, Closure $next, $role)
    {
        if (! $request->user()->hasRole($role)) {
            // Redirect...
        }

        return $next($request);
    }

}

     中间件参数可以在定义路由时通过 : 分隔中间件名和参数名来指定,多个中间件参数可以通过逗号分隔:

  Route::put('post/{id}', function ($id) {
      //
  })->middleware('role:editor');

终端中间件

     终端中间件,可以理解为一个善后的后台处理中间件。有时候中间件可能需要在 HTTP 响应发送到浏览器之后做一些工作,比如,Laravel 内置的 session 中间件会在响应发送到浏览器之后将 Session 数据写到存储器中,为了实现这个功能,需要定义一个终止中间件并添加 terminate 方法到这个中间件:

<?php

namespace Illuminate\Session\Middleware;

use Closure;

class StartSession
{
    public function handle($request, Closure $next)
    {
        return $next($request);
    }

    public function terminate($request, $response)
    {
        // 存储session数据...
    }
}

   terminate 方法将会接收请求和响应作为参数。定义了一个终端中间件之后,还需要将其加入到 app/Http/Kernel.php 文件的全局中间件列表中。

     当调用中间件上的 terminate 方法时,Laravel 将会从服务容器中取出一个该中间件的新实例,如果你想要在调用 handle 和 terminate 方法时使用同一个中间件实例,则需要使用容器提供的 singleton 方法以单例的方式将该中间件注册到容器中。

 

Guess you like

Origin www.cnblogs.com/mzhaox/p/11258055.html