Laravel 文档阅读:中间件

简介


中间件用来过滤项目中的 HTTP 请求,实际上 Laravel 项目中大量使用了中间件。例如,Laravel 中有一个验证用户是否认证的中间件,如果没有认证,就跳转到登录页面;如果认证了就进一步操作。
当然,中间件的作用不只是在认证上。CORS 中间件负责给项目中的相应设定正确的头部(Headers);日志中的中间件负责人记录项目中处理的所有请求信息。
Laravel 框架中包含了几种中间件,包括负责处理认证和 CSRF 保护的。所有中间件位于 app/Http/Middleware 目录下。

定义中间件

使用 Artisan 命令 make:middleware 创建中间件:

php artisan make:middleware CheckAge

这个命令会在 app/Http/Middleware 目录下创建一个 CheckAge 类。在这个中间件里,我么设定年龄大于18岁的可以进一步操作,小于等于18岁的重定向到用户控制台地址/home

age <=18){
       return redirect('/home');
       }
       return $next($request);
     }
}

允许请求的进一步操作,只需将请求实例 $request 放入 $next 中即可。
可以把中间件设想成,在最终要达到执行的业务代码前的一层层 「过滤网」,请求必须通过所有的中间件才能达到最终要执行的业务逻辑,否则被中间任何一个中间件拒绝,都会导致请求失败的。

中间件处理时机

一个中间件在处理请求之前或者之后进行任务处理,取决于中间件的代码逻辑放置的位置。 例如,下面的中间件在处理请求 “之前” 进行了一些任务操作:

而下面的中间件是在处理请求 “之后” 才进行的任务操作:

注册中间件


全局中间件

如果一个中间件在每次的 HTTP 请求时都要用到,那么把他列入 app/Http/Kernel.php$middleware 数组中即可。列入 $middleware 数组中的中间件又称为全局中间件。

为路由使用中间件

使用在路由身上的中间件是在 app/Http/Kernel.php 中的 $routeMiddleware 数组属性中定义的。如果你创建了一个新的给路由使用的中间件,就需要将他添加到 $routeMiddleware 这个数组里,并给中间件一个 key ——相当于中间件的名字。

// Within App/Http/Kenerl class····

protected $routeMiddleware = [
      'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
      'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth:class,
      'bindings' => \Illuminate\Auth\Middleware\SubstituteBinding:class,
      'can' => \Illuminate\Auth\Middleware\Authorize::class,
      'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
      'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];

使用中间件时,就用到了这个 Key:

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

也可以在一个路由上使用多个中间件:

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

也可以使用中间件的包含命名空间的完整类名(又称完全限定类名)使用中间件:

use App\Http\Middleware\CheckAge;

Route::get('admin/profile', function(){
//
})->middleware(CheckAge::class);

中间件组

中间件组中包含多个中间件,但它的使用和中间件是完全一样的。中间件组在 app/Http/Kenerl.php 中的 $middlewareGroups 属性中定义,每个中间件组还有一个对应的 key。
Laravel 项目中预设并使用了两个中间件组:webapi,它们分别用在了 routes/web.phproutes/api.php 上,前者是定义 Web 接口的地方,后者是定义 Api 接口的地方。这两个类型的接口,都有一些通用的中间件,所以放到一个组里进行管理。

/**
 * The application's route middleware groups.
 *
 * @var array
 */
protected $middlewareGroup = [
  'web' => [
       \App\Http\Middleware\EncryptCookies::class,
       \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
       \Illuminate\Session\Middleware\StartSession::class,
       \Illuminate\View\Middleware\ShareErrorsFromSession::class,
       \App\Http\Middleware\VerifyCsrfToken::class,
       \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

'api' => [
     'throttle:60,1',
     'auth:api',  
],
];

已经说过中间件组和中间件的使用是完全一样的,不过带来一个好处——一次定义,即可使用多个中间件。中间件组可以分配给路由和控制器 action使用:

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

注意,routes/web.php 文件里的中间件已将默认使用 web 中间件组,这是在 RouteServiceProvider 中定义的,在 routes/web.php 中定义路由时,时无需为路由额外分配 web 中间件组的。

中间件参数


可以为中间件传递参数。如果系统有一个需求——需要在验证角色之后才允许认证用户的进一步操作。以下以 CheckRole 中间件为例,它接受一个角色名作为参数。
中间件参数在 handle 方法的 $next参数之后定义。

user()->hasRole($role)){
               ..Redirect        
        }
      return $next($request);
    }
}

使用中间件参数的方式是在中间件后面加上一个 : ,然后在 : 后面跟上你要传递给中间件的参数。

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

在 Http 响应之后......


有时,中间件需要在 HTTP 响应请求之后才做处理工作。例如,包含在 Laravel 中的会话中间件会在响应发送到浏览器之后,再次保存会话数据。针对这样的需求,需要在中间件定义一个 terminate 方法,它会在响应发送到浏览器之后自动被调用。

terminate 方法接受两个参数,请求实例和响应实例。定义好之后,将它放在 app/Http/Kernel.php 添加在中间件列表中即可。
在调用 terminate 方法时,Laravel 是从服务容器中找到并创建一个新的中间件实例使用的,如果你只要使用同一个中间件实例,那么就要使用容器的 singleton 方法注册中间件了。

你可能感兴趣的:(Laravel 文档阅读:中间件)