ミドルウェアの書き方
では、実際にミドルウェアを実装していきましょう。
ミドルウェア用のクラスの作成方法
Laravelでは、ミドルウェアはapp/Http/Middlewareディレクトリにそれ専用のクラスを作成する約束になっているので、このディレクトリ内にリスト1のRecordIPAddress.phpファイルを作成してください。
<?php namespace App\Http\Middleware; // (1) use Closure; use Illuminate\Http\Request; class RecordIPAddress { public function handle(Request $request, Closure $next) // (2) { $ipAddress = $request->ip(); // (3) $path = $request->path(); // (4) print("<p>IPアドレスは".$ipAddress."でパスは".$path."</p>"); // (5) return $next($request); // (6) } }
ミドルウェアクラスを作成する場合、先述の通り、
app/Http/Middleware
ディレクトリ内に作成する必要があります。それに伴い、ミドルウェアクラスの名前空間もこのディレクトリに合わせ、
\App\Http\Middleware
とする必要があります。それを記述しているのが(1)です。
また、ミドルウェアクラスのクラス名は自由につけることができますが、handleという名のメソッドを記述する必要があります。それが(2)です。引数は2個で、第1引数がRequestインスタンスです。これは、Laravelで用意されたIlluminate\Http\Requestクラスのインスタンスであり、リクエスト処理に関するさまざまな情報を取得できます。第2引数はClosureインスタンスであり、こちらの使い方は後述します。
このメソッド内にミドルウェアとしての処理、つまり、リクエスト処理の前後に挿入したい処理を記述します。ここでは、IPアドレスを取得してどこかに記録するという処理を想定していますが、実際に記録するのではなくprint()して画面に表示するようにしています。
ソースコードとしては、IPアドレスを取得しているのがリスト1の(3)です。先述の通り、Requestクラスはそのメソッドを通じてリクエスト処理に関するさまざまな情報を取得できます。どういったメソッドがあるのかは、RequestクラスのAPI仕様書のページを参照してください。IPアドレスもそのうちの1つで、ip()メソッドで取得できます。
同じように、ルーティングパターンもpath()メソッドで取得しています。そうやって取得したIPアドレスとルーティングパターンを本来はどこかに記録するのでしょうが、ここでは(5)で画面表示しています。
リクエスト処理前後の区別
では、リスト1の(6)はどういった処理でしょうか。第2引数の$next()に第1引数を渡し、その戻り値をリターンしています。この記述は、このミドルウェアの処理(リスト1では(3)~(5)の処理)がリクエスト処理の前に実行されることを表します。
実は、ミドルウェアというのはリクエスト処理の前後に処理を挿入するもの、と説明してきましたが、この「前後」はどちらか選ぶ必要があり、前に挿入するのと、後に挿入するのとでhandle()メソッド内の記述パターンが変わってきます。もし、IPアドレスの記録をリクエスト処理後に行うならば以下の記述になります。
public function handle(Request $request, Closure $next) { $response = $next($request); // (1) $ipAddress = $request->ip(); // (2) $path = $request->path(); // (2) print("<p>IPアドレスは".$ipAddress."でパスは".$path."</p>"); // (2) return $response; // (3) }
(2)の3行はリスト1の(3)~(5)と同じで、ミドルウェアとして挿入したい処理そのものです。リスト1では、この処理の後に$next($request)を記述しましたが、ここでは(1)のように先に記述し、その戻り値を変数$responseとして一旦格納しておきます。その後、(2)のミドルウェアとしての処理が終了した後に、(3)のようにこの$responseをリターンします。
構文としてまとめると以下のようになります。
public function handle(Request $request, Closure $next) { 挿入したい処理 return $next($request); }
public function handle(Request $request, Closure $next) { $response = $next($request); 挿入したい処理 return $response; }
コマンドによるミドルウェアクラスの作成
ところで、リスト1で記述したミドルウェアクラスは、そのひな型をコマンドで作成することができます。プロジェクトルートディレクトリで以下の構文のコマンドを実行します。
php artisan make:middleware ミドルウェアクラス名
すると、app/Http/Middlewareディレクトリ内に指定のミドルウェアクラス名でひな型ファイルを作成してくれます。例えば、リスト1では、以下のコマンドとなります。
php artisan make:middleware RecordIPAddress
すると、リスト1の(3)~(5)が記述されていない状態のクラスファイルが作成されます(リスト1はそのひな型から(3)~(5)以外にも説明の関係上少し手を加えています)。
なお、ここで実行したartisanコマンドは、Laravelのコマンドで、今回行ったミドルウェアクラスの自動生成のように、Laravelでアプリを作成する際に便利な機能をいろいろと提供してくれます。
ミドルウェアの利用方法
ミドルウェアクラスが作成できたところで、このクラスを実際に利用していきましょう。
ミドルウェア利用の2ステップ
ミドルウェアを利用するためには、以下の2ステップが必要です。
- ミドルウェアクラスを登録する。
- ルーティングにミドルウェアを設定する。
順に行っていきましょう。
ミドルウェアクラスを登録する
今作成したミドルウェアを利用できるようにLaravelアプリ全体に登録します。これは、app/Http/Kernel.phpファイルへの記述です。なお、app/Http/Kernel.phpファイルはもともと存在するファイルであり、すでにさまざまなコードが記述されています。それらは基本的に変更しないようにして、連想配列プロパティ$routeMiddlewareにリスト2の太字の1行のみを追記するようにしてください。
〜省略〜 protected $routeMiddleware = [ 〜省略〜 "verified" => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, "recordipaddress" => \App\Http\Middleware\RecordIPAddress::class, ]; 〜省略〜
このKernelクラスは、さまざまなミドルウェアを管理、登録するクラスです。このクラスのプロパティに記述することで、ミドルウェアとして登録されるようになっています。そのミドルウェアの登録方法もさまざまあり、それぞれのプロパティが用意されています。その内で、ルーティングに利用するもの、つまり、リクエストの前後に処理を挿入する場合に利用するのが、$routeMiddlewareプロパティです。この連想配列に作成したミドルウェアクラスを登録します。キーとしてこのミドルウェアを識別するための任意の文字列を、値として、
作成したクラスの完全修飾名::class
を記述します。リスト2では、太字の部分にあるように、recordipaddressをミドルウェアの識別文字列(ミドルウェア名)としてリスト1で作成したRecordIPAddressクラスを登録しています。
これでミドルウェアの登録が完了しましたので、ステップ2に移ります。
ルーティングにミドルウェアを設定する
ルーティングにミドルウェアを登録して、実際にリクエスト処理の前後に処理を挿入します。これは、ルーティング登録の記述にmiddleware()メソッドをつなげる形になります。実際に記述してみましょう。routes/web.phpにリスト3のコードを追記してください。
Route::get("/chap5/middlewareTest", function() { return "<p>ミドルウェアのテスト。こちらはリクエスト処理。</p>"; // (1) })->middleware("recordipaddress"); // (2)
ここでは、前回紹介したコントローラクラスではなく、従来のコールバック関数を利用しています。通常はコントローラクラスを利用することになるでしょうが、記述方法は同じで、記述のポイントは(2)の部分です。ミドルウェアの登録は以下の構文となります。
Route::get(ルーティングパターン, …)->middleware(ミドルウェア名);
ここでは、get()での登録で記載していますが、もちろん、post()など他のルーティング登録メソッドでも同じです。また、第2引数は、コールバック関数でも、コントローラクラスでも同じですので、「…」としています。
ポイントは、このルーティング登録の記述に続けて、middleware()メソッドを実行し、その引数としてステップ1で登録したミドルウェア名を渡すことです。
リスト3までの記述がすべて終了したら、実際に以下のURLにアクセスしてください。
- http://localhost/firstlaravel/public/chap5/middlewareTest
すると、図2の画面が表示されます。なお、図2の「::1」という表示は、IPv6でのlocalhostのIPアドレスを表します。
リスト3で画面に表示する処理は(1)のみで、これは図2だと2行目にあたります。その前の1行目にIPアドレスとルーティングパターンが表示されており、この表示はリスト1の(5)の内容と一致します。これがまさにミドルウェアの処理であり、リクエスト処理であるリスト3の(1)の前に処理が挿入されたことを意味しています。
複数ミドルウェアの設定
1つのルーティングに複数のミドルウェアを設定することが可能です。その場合は、middleware()メソッドの引数にカンマ区切りで複数のミドルウェア名を並べます。例えば、以下のような記述です。
Route::post("/management/users/addUser", "management\UsersController@addUser") ->middleware("managerauth", "recordipaddress");
この場合は、managerauthという名前のミドルウェアと、recordipaddressという名前のミドルウェア2個の処理が挿入されます。