前回の記事ではログインボタンからログインした場合について解説しました。そちらのケースでは、RouteServiceProvider::HOMEを任意の値に変更する事でリダイレクト先を指定できました。今回はもう少し掘り下げ、ログインが必要なページにアクセスし強制的にログインページに飛ばされた場合について見てみましょう。

ログインページへ強制リダイレクト、からのログイン

未ログインの状態でログインが必要なページに遷移するとアクセスがガードされログインフォームに飛ばされますが、そこからログインした場合はどこにリダイレクトするでしょうか?前回の記事でRouteServiceProvider::HOMEに設定したトップページ(’/’)でしょうか?確認してみましょう。

以下のようにweb.phpを編集して’sayhi’というrouteを追加します。

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth'])->name('dashboard');

// ルート sayhi を追加
Route::get('/sayhi', function () {
    return sprintf('<h1>Hi, %s</h1>', auth()->user()->name);
})->middleware(['auth'])->name('sayhi');

require __DIR__.'/auth.php';

未ログインの状態でsayhiページを開いてみましょう。php artisan serveでwebサーバを起動しているならhttp://localhost:8000/sayhiから開けます。アクセスがガードされログインページに飛ばされるはずです。そしてログインすると。。。

sayhiページが表示されました。

redirect()->intended(…)、再び

認証が必要なページにアクセスしログインページに飛ばされた場合、ログイン後は元々アクセスしようとしていたページにリダイレクトされるようです。
これはどういうプロセスでそうなっているのでしょうか?

以下、AuthenticatedSessionControllerstore()を再掲します。

/**
 * Handle an incoming authentication request.
 *
 * @param  \App\Http\Requests\Auth\LoginRequest  $request
 * @return \Illuminate\Http\RedirectResponse
 */
public function store(LoginRequest $request)
{
    $request->authenticate();
 
    $request->session()->regenerate();
 
    return redirect()->intended(RouteServiceProvider::HOME);
}

前回は掘り下げなかった、redirect()->intended(...) の処理を追ってみましょう。
intended()は以下のように定義されています。

/**
 * Create a new redirect response to the previously intended location.
 *
 * @param  string  $default
 * @param  int  $status
 * @param  array  $headers
 * @param  bool|null  $secure
 * @return \Illuminate\Http\RedirectResponse
 */
public function intended($default = '/', $status = 302, $headers = [], $secure = null)
{
    $path = $this->session->pull('url.intended', $default);

    return $this->to($path, $status, $headers, $secure);
}

ここでの処理のポイントは3つです。

  1. sessionにurl.intendedがセットされていればその値をリダイレクト先とする
  2. url.intendedがセットされていなければ、引数で渡されたパスをリダイレクト先とする(ここではRouteServiceProvider::HOME)
  3. url.intendedも引数もセットされていない場合、引数のデフォルト値である’/’をリダイレクト先とする

ログインページに飛ばされた際、debugbarのsessionタブを開くとurl.intendedに元々アクセスしようとしていたURLがセットされているのが確認できます。

尚、sessionのpull()はセッションから値を取得し削除する為、ログイン後url.intendedはセッションに残っていません。

By hikaru