タイトル: ビューでリダイレクト
SEOタイトル: Laravel リダイレクト完全ガイド
| この記事の要点 |
|
基本: コントローラから redirect() を返す
Laravel のリダイレクトは「ビューを返す」のではなく「コントローラから RedirectResponse を返す」形が基本です。Blade ファイル内で直接リダイレクトはできません(HTML 出力に や JS を書く形になります)。
public function store(Request $request)
{
// ... 保存処理 ...
// 1. パス直指定
return redirect('/home');
// 2. 名前付きルート
return redirect()->route('home');
return redirect()->route('user.show', ['id' => 1]);
// 3. 直前のページに戻る
return redirect()->back();
return back(); // ヘルパー関数
// 4. アクション指定
return redirect()->action([HomeController::class, 'index']);
}
リダイレクトメソッド一覧
| メソッド | 用途 |
|---|---|
redirect('/path') | URL 直指定 |
redirect()->route('name', $params) | 名前付きルート(推奨) |
redirect()->back() / back() | 直前のページに戻る |
redirect()->intended('/default') | 認証ミドルウェアが保存した URL に戻る |
redirect()->action([Ctrl::class, 'method']) | コントローラアクション指定 |
redirect()->away('https://external') | 外部 URL(バリデーション通る) |
redirect()->guest($url) | 未認証時のリダイレクト先記録用 |
redirect()->refresh() | 同じ URL に再リクエスト |
フラッシュメッセージ・エラー・入力の保持
// フラッシュメッセージ(次のリクエストでのみ参照可能)
return redirect()->route('home')
->with('success', '保存しました');
// 複数
return redirect('/')->with([
'status' => 'ok',
'message' => '更新完了',
]);
// バリデーションエラー
return redirect()->back()
->withErrors($validator)
->withInput(); // 入力値を flash して old() で復元
// withInput で特定キーのみ
return back()->withInput($request->only(['email']));
// withInput で特定キー除外
return back()->withInput($request->except(['password']));
// withCookie
return redirect('/')->withCookie(cookie('name', 'value', 60));
Blade 側で受け取る:
{{-- フラッシュメッセージ --}}
@if (session('success'))
{{ session('success') }}
@endif
{{-- バリデーションエラー --}}
@error('email')
{{ $message }}
@enderror
{{-- 直前の入力値を復元 --}}
ログイン後の元のページに戻す: intended()
auth ミドルウェアは未認証ユーザを /login に飛ばすときに、「本来行きたかった URL」をセッションに記録します。ログイン処理後に intended() で読み出します。
public function login(Request $request)
{
if (Auth::attempt($request->only('email', 'password'))) {
$request->session()->regenerate();
// セッションに保存された intended URL があればそこへ
// なければ '/dashboard'
return redirect()->intended('/dashboard');
}
return back()->withErrors(['email' => '認証失敗']);
}
HTTP ステータスコードの指定
SEO 観点でリダイレクトの種別は重要です。Laravel デフォルトは 302 (Found)。永続的な移転は 301 (Moved Permanently) を明示します。
// 301 永続的リダイレクト
return redirect('/new-path', 301);
return redirect()->route('new.home', [], 301);
// 308 (Permanent Redirect, メソッド保持)
return redirect('/api/v2', 308);
// 303 (See Other, POST → GET 変換)
return redirect('/result', 303);
// レスポンスを後から書き換える
return redirect('/')->setStatusCode(301);
| コード | 意味 | 用途 |
|---|---|---|
| 301 | Moved Permanently | 恒久的な URL 変更(SEO 反映) |
| 302 | Found | 一時的(Laravel デフォルト) |
| 303 | See Other | POST 後の GET 遷移(PRG パターン) |
| 307 | Temporary Redirect | 一時的、メソッド保持 |
| 308 | Permanent Redirect | 恒久、メソッド保持 |
外部 URL へのリダイレクト
redirect() はオープンリダイレクト対策で外部 URL に飛ばすと例外が出る場合があります。明示的に外部に飛ばすなら away():
return redirect()->away('https://example.com/external');
// ❌ オープンリダイレクト脆弱性に注意
return redirect()->away($request->input('next')); // 危険
// ✅ ホワイトリスト検証してから away
$next = $request->input('next');
$allowed = ['example.com', 'partner.example.com'];
if (in_array(parse_url($next, PHP_URL_HOST), $allowed)) {
return redirect()->away($next);
}
abort(400);
Blade / フロント側からのリダイレクト
「ビュー内でリダイレクト」は本来コントローラ側でやるべきですが、どうしても HTML 描画後に飛ばしたい場合:
{{-- meta refresh(3秒後にリダイレクト) --}}
{{-- JavaScript --}}
Ajax / API リクエスト時の注意
Ajax / SPA から POST した場合、サーバが 302 を返してもブラウザは「Ajax レスポンス」として受け取るだけで自動遷移しません。フロント側で response.headers.get('Location') を見るか、JSON で URL を返すパターンが推奨です:
if ($request->wantsJson()) {
return response()->json([
'redirect' => route('home'),
'message' => '保存しました',
]);
}
return redirect()->route('home')->with('success', '保存しました');
FAQ
Q: redirect()->back() がトップに飛ぶ
A: 直前ページがセッション/Referer から取れない場合の挙動です。back(fallback: route('home')) でフォールバックを指定できます。
Q: 301 にすると以前のリダイレクト先がブラウザにキャッシュされて変更できない
A: ブラウザは 301 を強くキャッシュします。検証中は 302 を使い、本番リリース時のみ 301 に切り替えるのが安全。デバッグ時はシークレットウィンドウや DevTools の Disable Cache で。
Q: フラッシュメッセージが session() から取れない
A: web ミドルウェアグループに属しているか確認。routes/api.php はステートレスでセッションが無効なため with() は機能しません。