Day 5・入力の検証と横断的関心事 — バリデーション・ミドルウェア・Blade
バリデーション — 不正な入力をアプリの入口で弾く
何を・どこで・なぜ検証するのか。信頼できない外部入力を境界で止める考え方。
バリデーションとは何か
とは、ユーザーやAPIから送られてきた入力データが、アプリが期待する形になっているかを検証することです。「メールアドレスの形式か」「必須項目が空でないか」「数値が範囲内か」といったチェックを、処理を進める前に行います。
重要な前提は「外部から来る入力はすべて信頼できない」ということです。フォームは改ざんでき、APIには想定外の値が飛んできます。だからこそ、アプリの入口で一度きちんと弾く必要があります。
どこで弾くか — 三段の防御
- フロント(JavaScript)側: 入力しやすさ(UX)のための即時チェック。ただし改ざん可能なので信用してはいけない。
- サーバー(Laravel)側: 本当の防御線。ここを通った値だけを正しいものとして扱う。
- データベース側: NOT NULL や UNIQUE 制約で最後の砦を作る。
なぜサーバー側の検証が必須なのか
フロント側のチェックはブラウザの開発者ツールやAPIクライアントで簡単に回避できます。フロントだけに頼ると、不正な値がそのままDBに入り、後続の処理が壊れます。サーバー側検証は「省略できる保険」ではなく「必ず通す関所」です。
Laravelでの基本的な書き方
public function store(Request $request)
{
// 検証に失敗すると、自動的に前の画面へリダイレクトされ
// エラーメッセージがセッションに詰められる(APIなら422 JSON)
$validated = $request->validate([
'title' => ['required', 'string', 'max:255'],
'email' => ['required', 'email'],
'age' => ['nullable', 'integer', 'min:0', 'max:150'],
]);
// ここに来た時点で $validated は「検証済みの安全な値」だけ
Post::create($validated);
return redirect()->route('posts.index');
}ルールは「required(必須)」「email(形式)」「max:255(長さ)」のように、名前で意図が読めるよう設計されています。検証済みの値だけを取り出す「validate()」の戻り値を使うことで、想定外のキーを混入させない(マスアサインメント対策)効果もあります。
ありがちな落とし穴
リクエスト全体を「$request->all()」でそのまま保存すると、フォームに無い隠しフィールドまで書き込まれる恐れがあります。検証済みの値(validate()の戻り値)だけを保存対象にするのが安全です。
よく使うルール
- required / nullable: 必須か、空を許すか
- string / integer / boolean: 型
- min / max: 数値の範囲や文字列の長さ
- email / url / date: 形式
- unique:users,email: DBに重複が無いか
- confirmed: パスワード確認フィールドと一致するか
面接ではこう言う
「入力は外部から来る信頼できないデータなので、必ずサーバー側で検証してから処理に渡します。フロント側の検証はUXのためで、防御としては当てにしません。Laravelではルールを配列で宣言し、検証済みの値だけを使ってDBに書き込むことで、想定外の値の混入も防いでいます」
読んでも腑に落ちない所は、AIに噛み砕いてもらいましょう。
理解度チェック
答えられれば、面接で説明できる状態に一歩近づきます。
フロントエンド(JavaScript)のバリデーションだけに頼ってはいけない最大の理由は?
バリデーションを「どこで」行うべきか、その理由とともに説明してください。
記述式です。まず自分の言葉で答えを考えてから、模範解答を開いて自己採点してください。