簡単な紹介
アプリケーションにHTTP要求をフィルタリングするためのミドルウェアは、便利なメカニズムを提供します。例えば、Laravel内蔵ユーザが認証されていない場合、ユーザは、(例えば、ログインなど)認証されたかどうかを確認するミドルウェア、ミドルウェアは、ユーザが認証されている場合、ログインページにユーザをリダイレクトし、ミドルウェアは、要求が継続することを可能にします次のステップに進めます。
もちろん、認証に加えて、ミドルウェアは、他にも多くのタスクを処理するために使用することができます。たとえば:;ミドルウェアログレコードは、我々は、システムログを構築するシステムを容易にするために、すべての要求は、サイトにアクセスしてくださいCORSミドルウェアは、サイトを離れるに応じて適切なヘッダ(クロスドメイン)を追加するために使用することができます。
Laravelフレームワークは、その上の認証、CSRF保護ミドルウェアを含むミドルウェアの数、付属しています。すべてのミドルウェアは、に位置している app/Http/Middleware
ディレクトリ。
ミドルウェアの定義
職人コマンドによって、新しいミドルウェアを作成するには make:middleware
PHPの職人メイク:ミドルウェアCheckToken
このコマンドは、う app/Http/Middleware
、新たなミドルウェアのクラスのディレクトリを作成し CheckToken
、このミドルウェアでは、我々は唯一の提供を許可されている token
それ以外の場合は、アクセス経路tlar.comを要求し、指定された値に等しい、我々は百度にジャンプします。
場合 token != 'tlar.com'
、ミドルウェアは、HTTPが百度にリダイレクト戻り、そうでない場合、リクエストが渡されます。要求は、コールバック関数を呼び出すことによって受け継がれる $next
と電流を流します $request
。
注意:これが有効にこれを行うためのロジックミドルウェアミドルウェアのちょうど良い定義ですが、また、指定されたルートに登録します
最良の方法は、HTTPリクエストがミドルウェア「層」は、それぞれの層が要求をチェックし、特定のアクションの前に通過しなければならない到着すると、それを完全に拒絶することができるようにミドルウェアが見られることを理解すべきです。
注意:あなたは、コンストラクタのミドルウェアでプロンプトのいずれかのタイプに依存することができますので、すべての真ん中には、サービスコンテナで解決されています。
前/ミドルウェア後のリクエスト
ミドルウェアは、要求の実行がミドルウェア自体に依存する前または後の要求です。
例えば、以下のミドルウェアは、要求処理の前にタスクを実行します。
<?PHPの 名前空間のApp \のHttp \ミドルウェア。 使用閉鎖を。 クラスBeforeMiddleware { パブリック 関数ハンドル($要求、閉鎖$次) { // 执行动作 返す $次の($要求を)。 } }
以下のミドルウェアはリクエスト処理の後にそのタスクを実行します:
<?PHPの 名前空間のApp \のHttp \ミドルウェア。 使用閉鎖を。 クラスAfterMiddleware { パブリック 関数ハンドル($要求、閉鎖$次) { $応答 = $次($要求); // 执行动作 リターン $応答; } }
登録ミドルウェア
3つの中間点は、グローバルな中間体、およびルーティンググループミドルウェアです。
グローバル・ミドルウェア
あなたがミドルウェアを定義したい場合は、単に対応するミドルウェアクラスに追加し、各HTTP要求時に実行されている app/Http/Kernel.php
プロパティの配列 $middleware
缶で:
本当に必要な、または一般的にグローバルなビジネスレベルのミドルウェアミドルウェアに入れていない場合を除きます。
特定のルートに割り当てられたミドルウェア
如果你想要分配中间件到指定路由,首先应该在 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
方法以单例的方式将该中间件注册到容器中。