#はじめに
バリデーションに失敗した場合など直前のページにリダイレクトする場合があるが、
そのときに使用するreturn back()
について何が起こっているかを調べてみた。
Route::post('user/profile', function () {
// リクエストのバリデート処理…
return back(); // これが何をしているのか調べたい
});
#バージョン
PHP 7.4.20
Laravel 6.18.43
#前提知識
return back()
のback()の正体はグローバルに定義されたヘルパ関数である。
無効なフォームが送信された場合など、まれにユーザーを直前のページへリダイレクトする必要が起きます。グローバルなbackヘルパ関数を使用することで行なえます。この機能はセッションを利用しているため、back関数を呼び出すルートがwebミドルウェアグループを使用しているか、全セッションミドルウェアを確実に適用してください。
#backヘルパの中身を見る
backヘルパ関数は以下にあった。
\laravel\vendor\laravel\framework\src\Illuminate\Foundation\helpers.php
if (! function_exists('back')) {
/**
* Create a new redirect response to the previous location.
*
* @param int $status
* @param array $headers
* @param mixed $fallback
* @return \Illuminate\Http\RedirectResponse
*/
function back($status = 302, $headers = [], $fallback = false)
{
return app('redirect')->back($status, $headers, $fallback);
}
}
独自にbackというメソッドを定義していなければ、backメソッドを呼んだ時にbackヘルパが呼ばれる。
return back()
ではapp('redirect')->back(302, [], false)
を返している。
#app('redirect')->back(302, [], false)が何をしてるのか見る
app()自体もback同様にヘルパ関数であり、インスタンスを生成する。
app関数は、サービスコンテナのインスタンスを返します。
コンテナにより依存解決する、クラス名かインターフェイス名を渡すこともできます。
クラス名かインターフェイス名を渡すということだが、ここでは'redirect'という文字列を渡している。
\Illuminate\Foundation\Application.phpを見ると、'redirect'というエイリアスで[\Illuminate\Routing\Redirector::class]が登録されている。
public function registerCoreContainerAliases()
{
foreach ([
// 他もいっぱいあるけど、多いので'redirect'以外は省略
// ~~~
'redirect' => [\Illuminate\Routing\Redirector::class],
// ~~~
// 他もいっぱいあるけど、多いので'redirect'以外は省略
] as $key => $aliases) {
foreach ($aliases as $alias) {
$this->alias($key, $alias);
}
}
}
したがってapp('redirect')->back(302, [], false)
は
Redirectorクラスのインスタンスを生成し、そのインスタンスのbackメソッドを(302, [], false)という引数で呼び出しているということになる。
#Redirectorクラスのback(302, [], false)が何をしてるのか見る
backメソッドでは同クラス内にあるcreateRedirectメソッドを呼んでいる。
public function back($status = 302, $headers = [], $fallback = false)
{
return $this->createRedirect($this->generator->previous($fallback), $status, $headers);
}
#createRedirect($this->generator->previous($fallback), $status, $headers)が何をしてるのか見る
createRedirectメソッドの中ではtap関数にRedirectResoponseクラスのインスタンスとクロージャを渡している。
protected function createRedirect($path, $status, $headers)
{
return tap(new RedirectResponse($path, $status, $headers), function ($redirect) {
if (isset($this->session)) {
$redirect->setSession($this->session);
}
$redirect->setRequest($this->generator->getRequest());
});
}
tap関数はこれまたヘルパであり、第二引数のクロージャに第一引数を渡す(使うと見た目がすっきりする...らしい)。
第一引数はRedirectResponseクラスのインスタンスであり、コンストラクタとしてback関数から受け取った引数を渡す。
引数 | 値 |
---|---|
$path | generatorで作成された遷移直前のページのURI |
$status | HTTPレスポンスコード302(リダイレクト) |
$headers | HTTPレスポンスに設定するヘッダ |
第二引数のクロージャではRedirectResponseクラスのインスタンスを受け取る。
Redirectorインスタンスにsessionが設定済の場合はRedirectorインスタンスが保持するsession変数をsessionに格納する。
その後setRequestメソッドで、生成したRedirectResponseインスタンスの$requestにgeneratorクラスのgetRequestメソッドで取得したrequestをセットする。
tap関数の戻り値は第一引数で受け取ったインスタンスになるので、
createRedirectで作成したRedirectResponseインスタンスが最終的なreturn back();の戻り値となり、リダイレクトが行われる。
#結論
return back()の戻り値は、直前のページのURI・レスポンスコード302を保持したRedirectResponseクラスのインスタンスである。