概要
ミドルウェアを作成・登録する手順は以下のとおり
artisan
でミドルウェアを作成- ミドルウェアの処理内容を記述
- ミドルウェアを登録
- ルーティングでミドルウェアの組み込みを設定
参考サイト:【Laravel】ルーティングのミドルウェアとは?作成手順と実例
準備
以下のルーティング、コントローラー、ビューを準備する。
ルーティング:
1 |
Route::get('middleware', 'MiddlewareExampleController@show'); |
コントローラー:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class MiddlewareExampleController extends Controller { public function show() { HelperController::console_log('in action before calling view'); return view('middleware_test'); } } |
ビュー:
1 2 3 4 5 6 7 8 9 10 11 |
<!DOCTYPE html> <html lang="ja" dir="ltr"> <head> <meta charset="utf-8"> <title>middlewareテスト</title> </head> <body> <h1>ミドルウェアテスト</h1> {{ App\Http\Controllers\HelperController::console_log('in view') }} </body> </html> |
なおコントローラーとビューで、以下のヘルパーコントローラーのconsole_log()
メソッドで表示をさせていて、ミドルウェアでもこのメソッドを使っていく。
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class HelperController extends Controller { public static function console_log($var) { echo '<script>console.log(', json_encode($var, JSON_UNESCAPED_UNICODE), ');</script>'; } }み |
ミドルウェアの作成・登録手順
ミドルウェアの作成
以下のコマンドでミドルウェアのファイルを作成。
php artisan make:middleware ミドルウェア名
ファイルはapp/Http/Middleware
ディレクトリー下に作成される(middlewareはuncountableだが、状況によってはmiddlewaresという複数形もあり得るらしい)。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ php artisan make:middleware SampleBeforeMiddleware Middleware created successfully. $ ls -Al app/Http/Middleware/ 合計 32 -rw-rw-r--. 1 vagrant vagrant 469 9月 7 16:19 Authenticate.php -rw-rw-r--. 1 vagrant vagrant 335 9月 7 16:19 CheckForMaintenanceMode.php -rw-rw-r--. 1 vagrant vagrant 294 9月 7 16:19 EncryptCookies.php -rw-rw-r--. 1 vagrant vagrant 582 9月 7 16:19 RedirectIfAuthenticated.php -rw-rw-r--. 1 vagrant vagrant 342 9月 13 19:14 SampleBeforeMiddleware.php -rw-rw-r--. 1 vagrant vagrant 340 9月 7 16:19 TrimStrings.php -rw-rw-r--. 1 vagrant vagrant 436 9月 7 16:19 TrustProxies.php -rw-rw-r--. 1 vagrant vagrant 463 9月 7 16:19 VerifyCsrfToken.php |
作成されたファイルの内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php namespace App\Http\Middleware; use Closure; class SampleBeforeMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { return $next($request); } } |
ミドルウェアの処理内容の記述
ミドルウェアの処理には、その実行タイミングに応じた書き方がある。
それらについては後述するが、ここでは仮にhandle()
メソッドに別途準備したconsole_log()
で表示をさせている。
1 2 3 4 5 6 |
public function handle($request, Closure $next) { \App\Http\Controllers\HelperController::console_log('in middleware'); return $next($request); } |
ミドルウェアの登録
登録の種類と手順
作成したミドルウェアはapp/Http/Kernel.php
ファイルで登録する。
登録方法により、グローバル登録、ルーティング登録、グループ登録の3種がある。
グローバル登録
Kernel
クラスの$middleware
プロパティーに作成したミドルウェアを加えると、すべてのルーティングにミドルウェアが適用される。
以下の例では、デフォルトで生成・登録されるミドルウェアに加えてSampleBeforeMiddleware
を登録している。
1 2 3 4 5 6 7 8 |
protected $middleware = [ \App\Http\Middleware\TrustProxies::class, \App\Http\Middleware\CheckForMaintenanceMode::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \App\Http\Middleware\SampleBeforeMiddleware::class, ]; |
ルート登録
Kernel
クラスの$routeMiddleware
プロパティーに、名前とともにミドルウェアを登録する。
以下の例では、デフォルトで生成・登録されるミドルウェアに加えて、SampleBeforeMiddleware
を'routed_middleware'
という名前で登録している。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'test_name' => \App\Http\Middleware\SampleBeforeMiddleware::class, ]; |
グループ登録
Kernel
クラスの$middlewareGroups
プロパティーに、グループ名をキーとし、ミドルウェアの配列を値として登録する。
以下の例では、デフォルトで登録される2つのグループ'web'
、'api'
に加えて’test'
というグループを追加し、そのグループにSampleBeforeMiddleware
を登録している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'test_group' => [ \App\Http\Middleware\SampleBeforeMiddleware::class, ], ]; |
ミドルウェアの適用
グローバル登録の場合は全適用
グローバル登録されたミドルウェアは、ルーティング設定がなくても全てのコントローラーのアクションに適用される。
この結果、アプリケーションの任意のURLにアクセスすると、ブラウザーのコンソールに以下の様に表示される。
1 2 3 |
in SampleBeforeMiddleware@handle in show action before calling view in view |
ルーティングファイルでの適用
ルート登録・グループ登録のいずれの場合も、ルーティングで特定のルートにミドルウェアを適用できる。
ルートミドルウェアの場合は登録した名前で適用。
1 2 |
Route::get('middleware', 'MiddlewareExampleController@show') ->middleware('test_name'); |
グループミドルウェアの場合は登録したグループ名で適用。
1 2 |
Route::get('middleware', 'MiddlewareExampleController@show') ->middleware('test_group'); |
結果はいずれも同じで、以下のようにブラウザーのコンソールに表示される。
1 2 3 |
in SampleBeforeMiddleware@handle in show action before calling view in view |
コントローラーのコンストラクターでの適用
コントローラーのコンストラクターの中で、middleware()
メソッドの引数にミドルウェアの登録名やグループ名を指定して適用できる。
この場合、ルーティングファイルで設定しなくても、当該コントローラーのアクションに対してミドルウェアが適用される。
以下はルートミドルウェア名で登録する場合。
1 2 3 4 5 6 7 8 9 10 11 12 |
class MiddlewareExampleController extends Controller { public function __construct() { $this->middleware('test_name'); } public function show() { HelperController::console_log('in show action before calling view'); return view('middleware_test'); } } |
以下はグループ名で適用する場合。
1 2 3 |
public function __construct() { $this->middleware('test_group'); } |
結果はいずれも同じで、以下のようにブラウザーのコンソールに表示される。
1 2 3 |
in SampleBeforeMiddleware@handle in show action before calling view in view |
ミドルウェアの条件
before middleware
コントローラーが呼ばれる前に実行すべき文を、$next($request)
の実行より前に書く。
このとき、$request
からパラメーターを取り出し、その条件に応じた処理をさせることができる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class SampleBeforeMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { // ここに$requestに対する条件に応じた処理を書く \App\Http\Controllers\HelperController::console_log('in SampleBeforeMiddleware@handle'); return $next($request); } } |
after middleware
handle()
メソッド内で$next($request)
を実行した後に、その結果に応じた処理を記述すると、コントローラーの実行後・ビュー表示前にその内容が処理される。
terminate()
メソッド内に処理を記述すると、それらはビュー表示後に実行される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class SampleAfterMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $response = $next($request); // ここに$responseに対する条件に応じたコントローラー実行後の処理を書く \App\Http\Controllers\HelperController::console_log('in SampleAfterMiddleware@handle'); return $response; } public function terminate($request, $response) { // ここにビュー表示後の処理を書く \App\Http\Controllers\HelperController::console_log('in SampleAfterMiddleware@terminate'); } } |
ここで、この2つのミドルウェアをKernel
クラスでグループ登録する。
1 2 3 4 5 6 7 8 |
protected $middlewareGroups = [ .... 'middleware_group' => [ \App\Http\Middleware\SampleBeforeMiddleware::class, \App\Http\Middleware\SampleAfterMiddleware::class, ], ]; |
ルーティングへの適用はグループ名で。
1 2 |
Route::get('middleware', 'MiddlewareExampleController@show') ->middleware('middleware_group'); |
実行すると、ブラウザーのコンソールに以下の様に表示される。
1 2 3 4 5 |
in SampleBeforeMiddleware@handle in show action before calling view in SampleAfterMiddleware@handle in view in SampleAfterMiddleware@terminate |
なお、上記ではルーティングファイルでミドルウェアを適用したが、コントローラーのコンストラクターで適用しても結果は同じ。
only/except~部分指定と除外
準備
コントローラーのコンストラクターでミドルウェアを適用する場合、コントローラーの特定のアクションのみに適用したり、適用除外にしたりすることができる。
まず、以下のようなルーティング定義、コントローラーを準備する。ミドルウェアとビューはこれまで使ってきたものと同じ。
ルーティング:
1 2 |
Route::get('middleware/select', 'MiddlewareExampleController@select'); Route::get('middleware/ignore', 'MiddlewareExampleController@ignore'); |
コントローラー:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class MiddlewareExampleController extends Controller { public function __construct() { $this->middleware('test_group'); } public function select() { HelperController::console_log('in select action before calling view'); return view('middleware_test'); } public function ignore() { HelperController::console_log('in ignore action before calling view'); return view('middleware_test'); } } |
ここで2つのURLをブラウザーで指定すると、それぞれ以下の様に表示される。
middleware/select
1 2 3 4 5 |
in SampleBeforeMiddleware@handle in select action before calling view in SampleAfterMiddleware@handle in view in SampleAfterMiddleware@terminate |
middleware/ignore
1 2 3 4 5 |
in SampleBeforeMiddleware@handle in ignore action before calling view in SampleAfterMiddleware@handle in view in SampleAfterMiddleware@terminate |
only()~部分指定
コンストラクター内のmiddleware()
に対してonly()
メソッドを実行すると、引数の配列で与えたアクション群に対してだけミドルウェアが適用される。
以下の例ではselect()
メソッドのみ適用対象としていて、ignore()
メソッドにはミドルウェアは適用されない。
1 2 3 |
public function __construct() { $this->middleware('test_group')->only(['select']); } |
この結果、middleware/select
にアクセスした結果は先の結果と変わらないが、middleware/ignore
にアクセスした場合はミドルウェアが実行されず、以下のようなコンソール表示になる。
1 2 |
in ignore action before calling view ignore:9 in view |
except()~除外指定
コンストラクター内のmiddleware()
に対してexcept()
メソッドを実行すると、引数の配列で与えたアクション群に対してだけミドルウェアが適用されなくなる。
以下の例ではignore()
メソッドのみ適用除外となり、ミドルウェアが適用されない。
1 2 3 |
public function __construct() { $this->middleware('test_group')->except(['ignore']); } |
結果はonly()
の場合と同じになる。