【Laravel11】Middlewareの処理中にAuth Facadeでnullやfalseが取得されるときの対処法【Auth::】
こんにちは、システム開発部の榎木です。
今回は、Laravel 11のリリースに伴うミドルウェア周りの記法変更についてです。Laravelユーザーの皆さんの多くは、自作のミドルウェアを追加する際にKernel.php
ではなくbootstrap/app.php
に記載するようになった変更があることをご存じかと思います。
この際、任意に追加したミドルウェアの中でAuthを使用したものの結果がnullやfalseなどになってしまい、
意図した結果がどうしても得られなかった場合があったので、その対処法についてLaravel10とLaravel11を比べながら書きたいと思います。
追加したい任意作成したMiddlewareの例
こんな感じのミドルウェアを追加したい!という方向けです。
namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Symfony\Component\HttpFoundation\Response; class HogeMiddleware { /** * Handle an incoming request. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next): Response { $user = Auth::user(); // ユーザーの特定のフラグがfalseであれば特定のルートリダイレクトさせたいみたいな場合 if ($user->someThingFlag === false) { return redirect()->route('route.something'); } return $next($request); } }
(あくまで例です。ユーザーが取得できなかったらエラーになるじゃんとかは一旦胸の内に秘めておいてください。)
Middleware追加方法:Laravel10と11の違い
Laravel10で任意のミドルウェアを追加する場合、Kernel.php
の $routeMiddlewareに追記していましたね。
/** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array<string, class-string|string> */ protected $routeMiddleware = [ 'hoge' => \App\Http\Middleware\HogeMiddleware::class, ];
この際、ミドルウェア中でAuthファサードを使っていても問題なく使えていました。(自己比)
(ミドルウェアでAuth使えたらいいなってタイミングは往々にしてあるとおもいます。)
では、Laravel11ではこのKenel.phpに当たる部分がapp.phpに変更されその内容がどうなったかというと、
return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', commands: __DIR__.'/../routes/console.php', health: '/up', then: function () { Route::middleware([ 'web', HogeMiddleware::class, ]); } ) ->withMiddleware(function (Middleware $middleware) { $middleware->web(prepend: [ HogeMiddleware::class, ]); }) ->withExceptions(function (Exceptions $exceptions) { // })->create();
このようになります。ずいぶん……鍛え直したな………という感じですね。
正直あんまりまだ慣れません。
このまま使うとAuthファサードを使ってもnullとかfalseとか、とにかく認証ユーザーやそれにまつわる取得ができません(でした)。
解決法(本題)
Laravel10にも普通にいましたが、priorityを設定することです。
10ではLaravelデフォルトのミドルウェアが下記のようにグルーピングされていましたね。
protected $middlewareGroups = [ '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, ], ...
Laravel10までは $middlewareGroups にデフォルトのミドルウェアがまとまっていました。
また任意に作成したミドルウェアは$middlewarePriorityを設定すれば任意に実行順を変更することができました。
この標準ミドルウェアの実行後に、登録した任意作成のミドルウェアが実行されていたのであんまり気にしたことがなかったです。
確認したところ、Authでユーザーの情報に触れるには下記2つのミドルウェアの先行実行が必要でした。
\Illuminate\Cookie\Middleware\EncryptCookies::class, \Illuminate\Session\Middleware\StartSession::class,
この2つの実行前にAuthをミドルウェア中に使用すると、意図したとおりの情報を取得できないようです。
このため、laravel11からはpriorityを設定してミドルウェアの実行順序を積極的に制御してあげるようにしました。
->withMiddleware(function (Middleware $middleware) { $middleware->priority([ \Illuminate\Cookie\Middleware\EncryptCookies::class, \Illuminate\Session\Middleware\StartSession::class, \App\Http\Middleware\HogeMiddleware::class, ]); $middleware->web(prepend: [ HogeMiddleware::class, ]); })
これでAuthファサードの準備が整って、ユーザーにまつわるデータが取得できるようになりました。
おわり
とくに締めとかはないです。
正直10のときはミドルウェアの実行順を制御できることは知ってるけど積極的には制御してなかったです。
公式ドキュメント読めばわかるといえばわかるのですが、Laravel11の日本語記事みたいなのもっと増えてほしいなとそれはそれで思って書いてみました。