Laravel11 guestミドルウェアのリダイレクト先の変更方法が変わっていた

沖縄チームのキリです。Laravel10のプロジェクトとLaravel11のプロジェクト両方触っていたのですが、Laravel11でログイン中ユーザーがログイン画面にアクセスした際にリダイレクトされるダッシュボードのURLを変更しようとしたときに今まで変更をかけていたミドルウェアクラスが作業ディレクトリ内に存在しないことに気がつきました。

guestミドルウェアはユーザーがログイン中であればダッシュボードにリダイレクトする処理を行っています。ゲストユーザー専用の画面、主にはログイン済のユーザーがログイン画面にアクセスした際などに使われています。

Laravel10まではApp\Http\Kernel.phpにてミドルウェアの登録が行われており、guestミドルウェアの実態はApp\Http\Middleware\RedirectIfAuthenticatedクラスがバインディングされています。リダイレクト先を変えたい場合はこちらのミドルウェアクラスのhandleメソッドを変更すれば実現できました。

class RedirectIfAuthenticated
{
    public function handle(Request $request, Closure $next, ...$guards)
    {
        $guards = empty($guards) ? [null] : $guards;

        foreach ($guards as $guard) {
            if (Auth::guard($guard)->check()) {
                // ここかRouteServiceProvider::HOMEを変更でリダイレクト先を変更可能
                return redirect(RouteServiceProvider::HOME);
            }
        }

        return $next($request);
    }
}

Laravel11ではKernelクラスがなくなりbootstrap/app.phpでミドルウェアの設定を行うようになりました。そしてApp\Http\Middlewareにあったミドルウェアクラスはほとんどなくなっています。先程のRedirectIfAuthenticatedミドルウェアはvendorディレクトリのものを参照するようになっています。リダイレクト先は/dashboardか/homeのルーティングが存在すればそちらを返し、なければトップページにリダイレクトするようになっているようです。

class RedirectIfAuthenticated
{
    // ~中略~

    protected function defaultRedirectUri(): string
    {
        foreach (['dashboard', 'home'] as $uri) {
            if (Route::has($uri)) {
                return route($uri);
            }
        }

        $routes = Route::getRoutes()->get('GET');

        foreach (['dashboard', 'home'] as $uri) {
            if (isset($routes[$uri])) {
                return '/'.$uri;
            }
        }

        return '/';
    }
}

リダイレクト先の変更方法を検索したところRedirectIfAuthenticatedクラスを継承したカスタムミドルウェアを作成してguestミドルウェアを上書きするというような内容のものが見つかりました。非常に回りくどいやり方でスッキリしなかったのでコードを追ってみることにしました。

    protected function redirectTo(Request $request): ?string
    {
        return static::$redirectToCallback
            ? call_user_func(static::$redirectToCallback, $request)
            : $this->defaultRedirectUri();
    }

    public static function redirectUsing(callable $redirectToCallback)
    {
        static::$redirectToCallback = $redirectToCallback;
    }

どうやらRedirectIfAuthenticated::$redirectToCallbackにコールバック関数が登録されている場合、コールバックの返り値がリダイレクト先になり、未登録の場合に先程のdefaultRedirectUri()が呼び出されるようです。$redirectToCallbackの登録はRedirectIfAuthenticated::redirectUsing($callback)で出来そうですね。

結論

bootstrap/app.phpのwithMidleware()内にて

$middleware->redirectUsersTo(function (\Illuminate\Http\Request $request) {
    return 'リダイレクト先URL';
});

これでOKです。redirectUsersTo()の内部でRedirectIfAuthenticated::redirectUsing()が呼び出されコールバックが登録されます。

参考になれば幸いです。