ミドルウェアとは?
Laravelの日本語ドキュメントがまとめられているReaDoubleのミドルウェアの項目には以下のようにあります。
ミドルウェアは、アプリケーションに入るHTTPリクエストを検査およびフィルタリングするための便利なメカニズムを提供します。たとえば、Laravelには、アプリケーションのユーザーが認証されていることを確認するミドルウェアが含まれています。ユーザーが認証されていない場合、ミドルウェアはユーザーをアプリケーションのログイン画面にリダイレクトします。逆に、ユーザーが認証されている場合、ミドルウェアはリクエストをアプリケーションへ進めることを許可します。
ミドルウェア 8.x Laravel
HTTPリクエストを検査、そしてフィルタリングするためのメカニズムとあります。ユーザーからのリクエストを受けてコントローラーに処理を渡す手前でなんらかの処理をしたい場合に活用することができます。
例えば、ログイン済みのユーザーでしか閲覧できないような会員限定のページにアクセス制限をかけたり、本登録が済んでいないユーザーに本登録画面へのリダイレクト処理をしたりすることができます。
また、Laravel本体のミドルウェアをみてみると\App\Http\Middleware\VerifyCsrfToken::class
がありCSRFトークンのチェックをしていたりします。セッションに関する処理もここでしているようです。
ミドルウェアの命名規則
ミドルウェアクラスの命名規則として、動詞はじまりのクラス名にしましょう。また、何らかの条件をチェックしてリダイレクトをしたりするようなミドルウェアには、以下の動詞を使うとわかりやすいかもしれません。
- verify
- validate
- check
- require
- ensure
ミドルウェアを使うシナリオ
今までに経験したミドルウェアを使うシナリオとして、以下がありました。
- ログイン済みのユーザーがどうかをチェックする(authミドルウェア)
\App\Http\Middleware\Authenticate::class
に定義されています。- 管理画面(front)とサービス画面(admin)でガード(Guard)を分けてマルチ認証をする場合には、
auth:front
やauth:admin
のようにすることでそれぞれのガードに対してログイン状態をチェクすることができました。
- メール認証済みのユーザーかどうかをチェックする(verifiedミドルウェア)
\App\Http\Middleware\EnsureEmailIsVerified::class
に定義されています。- メールによる本人確認が済んでいるユーザーかどうかを判定するミドルウェアです。
- 本登録済みのユーザーかどうかをチェックする(registeredミドルウェア)
- 自作でプロフィールの特定の項目が空かどうかをチェックして仮登録かどうかをチェックする
\App\Http\Middleware\EnsureProfileRegistered::class
を定義して、仮登録の場合は本登録画面へリダイレクトをさせるミドルウェアを作成しました。
- 自作でプロフィールの特定の項目が空かどうかをチェックして仮登録かどうかをチェックする
- マイページでログイン中のユーザーが所有している通知のみ閲覧できるようにする(is_my_addressミドルウェア)
- 自作でマイページでログイン中のユーザーが所有している通知(DatabaseNotificationモデル)のみ閲覧できるようにするためのミドルウェアを作成しました。ルーティングの自動モデルバインディングを利用しつつも、他のユーザーの通知を閲覧できないように制限する必要がありました。
ミドルウェアの参考例
ミドルウェアの参考例として、前章の4番目のシナリオにあったログイン中のユーザーが所有している通知かどうかを判定するミドルウェアを取り上げます。
artisanコマンドでミドルウェアを作成する
php artisan make:middleware EnsureIsMyNotification
app/Http/Kernel.phpにミドルウェアを登録する
作成したクラスをrouteで使うミドルウェアとして登録します。is_my_notification
という名前でミドルウェアを指定できるようにします。
protected $routeMiddleware = [ // ....省略 'is_my_notification' => \App\Http\Middleware\EnsureIsMyNotification::class ];
EnsureIsMyNotificationクラスにロジックを記述していきます
ユーザーがログイン済みで、かつそのユーザーがルーティングでモデルバインディングされたnotificationクラスの所有者だった場合にのみ閲覧権限をあたえて、それ以外の場合はトップページにリダイレクトさせます。
具体的にはEnsureIsMyNotificationクラスに以下のように記述していきます。
<?php
namespace App\Http\Middleware;
use Closure;
class EnsureIsMyNotification
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if(!$request->user()
|| $request->user()->getMorphClass() !== $request->route()->notifiable_type
|| $request->user()->id !== $request->route()->notifiable_id
){
return redirect('/');
}
return $next($request);
}
}
ルーティングを記述しているweb.phpにミドルウェアを指定します。
以下のようにしてis_my_notification
ミドルウェアを指定したのちに、その中にミドルウェアを適用したいルート処理を記述すれば完了です。
Route::middleware(['is_my_notification'])->group(function () { Route::get('/mypage/notifications/{notification}', 'MyPage\ShowNotification'); });