CG
ルート
Route::post('/product/validate', [ProductController::class, 'validateStore']);
Route::post('/product/store', [ProductController::class, 'store']);
コントローラー
public function validateStore(Request $request)
{
$validated = $request->validate([
'item_cd' => 'required',
'name' => 'required',
]);
return back()
->withInput()
->with('confirm', true);
}
with('confirm', true)
セッションにフラグを保存
Laravelの with() 次の画面描画時だけ使える一時変数
blade
@if(session('confirm'))
<script>
document.addEventListener('DOMContentLoaded', function() {
const modal =
new bootstrap.Modal(
document.getElementById('confirmModal')
);
modal.show();
});
</script>
@endif
<form method="POST"
action="{{ route('product.store') }}">
@csrf
<input type="hidden"
name="item_cd"
value="{{ old('item_cd') }}">
<input type="hidden"
name="name"
value="{{ old('name') }}">
<button type="submit">
OK
</button>
</form>
with()の正体
return view('product')
->with('name', 'コーラ');
blade
{{ $name }}
これは、View変数を渡している。
しかし今回のこれは違う。
redirect時のwith()
return back()
->with('confirm', true);
back() は RedirectResponse を返します。
ここでの with() は、セッションに一時保存。
これが超重要。
CD
初学者がつまずくポイント① — HTTPはステートレス
// routes/web.php
// バリデーション専用ルート(DBには保存しない)
Route::post('/products/validate', [ProductController::class, 'validateOnly'])
->name('products.validateOnly');
// 実際の保存ルート(バリデーション済みが前提)
Route::post('/products/store', [ProductController::class, 'store'])
->name('products.store');
// app/Http/Controllers/ProductController.php
class ProductController extends Controller
{
/**
* ステップ1: バリデーションだけ行い、データをセッションに保存してViewへ戻す
*/
public function validateOnly(Request $request)
{
// バリデーション(失敗すると自動で入力ダイアログに戻る)
$validated = $request->validate([
'name' => 'required|string|max:100',
'price' => 'required|integer|min:0',
// 他のフィールドも追加してください
]);
// ⚠️ つまずきポイント③ で後述
// バリデーション済みデータをセッションに「一時保存」する
session(['product_confirm' => $validated]);
// 確認モーダルを表示するページ(またはダイアログ元のページ)へリダイレクト
return redirect()->route('products.create')
->with('show_confirm_modal', true); // モーダル表示フラグも一緒に渡す
}
/**
* ステップ2: セッションからデータを取り出してDBに保存
*/
public function store(Request $request)
{
// セッションからバリデーション済みデータを取得
$data = session('product_confirm');
// セッションにデータがない場合(直接アクセスなど)は弾く
if (!$data) {
return redirect()->route('products.create')
->with('error', '不正なアクセスです。もう一度入力してください。');
}
// DBに保存
Product::create($data);
// セッションから確認データを削除(使い終わったので)
session()->forget('product_confirm');
return redirect()->route('products.index')
->with('success', '登録が完了しました');
}
}
方法保持期間主な用途
| 方法 | 保持期間 | 主な用途 |
|---|---|---|
session(['key' => $value]) |
明示的に削除するまで残る | データの一時保存 |
->with('key', $value) |
次の1リクエストだけ(フラッシュデータ) | 成功メッセージ、フラグの受け渡し |
blade
{{-- resources/views/products/create.blade.php --}}
{{-- 入力ダイアログ(フォーム) --}}
<form action="{{ route('products.validateOnly') }}" method="POST">
@csrf
<input type="text" name="name" value="{{ old('name') }}">
<input type="number" name="price" value="{{ old('price') }}">
{{-- バリデーションエラーの表示 --}}
@error('name')
<p class="error">{{ $message }}</p>
@enderror
<button type="submit">登録</button>
</form>
{{-- 確認モーダル --}}
{{-- ⚠️ つまずきポイント④ で後述 --}}
@if(session('show_confirm_modal'))
<div id="confirmModal" style="display: block;">
<p>以下の内容で登録しますか?</p>
{{-- セッションに保存したデータを表示 --}}
<p>商品名: {{ session('product_confirm.name') }}</p>
<p>価格: {{ session('product_confirm.price') }}</p>
{{-- OKボタン → storeルートへPOST --}}
<form action="{{ route('products.store') }}" method="POST">
@csrf
<button type="submit">OK</button>
</form>
{{-- キャンセルボタン → モーダルを閉じるだけ(JS) --}}
<button onclick="closeModal()">キャンセル</button>
</div>
@endif
<script>
function closeModal() {
document.getElementById('confirmModal').style.display = 'none';
}
</script>