LLaravel Bootcamp

Day 5入力の検証と横断的関心事 — バリデーション・ミドルウェア・Blade

バリデーション — 不正な入力をアプリの入口で弾く

何を・どこで・なぜ検証するのか。信頼できない外部入力を境界で止める考え方。

バリデーションとは何か

とは、ユーザーやAPIから送られてきた入力データが、アプリが期待する形になっているかを検証することです。「メールアドレスの形式か」「必須項目が空でないか」「数値が範囲内か」といったチェックを、処理を進める前に行います。

重要な前提は「外部から来る入力はすべて信頼できない」ということです。フォームは改ざんでき、APIには想定外の値が飛んできます。だからこそ、アプリの入口で一度きちんと弾く必要があります。

どこで弾くか — 三段の防御

  • フロント(JavaScript)側: 入力しやすさ(UX)のための即時チェック。ただし改ざん可能なので信用してはいけない。
  • サーバー(Laravel)側: 本当の防御線。ここを通った値だけを正しいものとして扱う。
  • データベース側: NOT NULL や UNIQUE 制約で最後の砦を作る。

なぜサーバー側の検証が必須なのか

フロント側のチェックはブラウザの開発者ツールやAPIクライアントで簡単に回避できます。フロントだけに頼ると、不正な値がそのままDBに入り、後続の処理が壊れます。サーバー側検証は「省略できる保険」ではなく「必ず通す関所」です。

Laravelでの基本的な書き方

PHP
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');
}
コントローラ内で validate() を呼ぶ最小の例

ルールは「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に噛み砕いてもらいましょう。

理解度チェック

答えられれば、面接で説明できる状態に一歩近づきます。

Q1

フロントエンド(JavaScript)のバリデーションだけに頼ってはいけない最大の理由は?

Q2

バリデーションを「どこで」行うべきか、その理由とともに説明してください。

記述式です。まず自分の言葉で答えを考えてから、模範解答を開いて自己採点してください。