【Laravel】動的なフォーム生成とバリデーションの両立方法|フィールドの条件表示と安全な処理設計

【Laravel】動的なフォーム生成とバリデーションの両立方法|フィールドの条件表示と安全な処理設計 Laravel

Laravelでフォームを扱う際、画面上で入力項目が動的に変化するケース(チェックボックスの有無に応じて入力欄を表示/非表示など)はよくあります。

しかし、クライアント側でフィールドが非表示になっていても、サーバー側ではその存在を前提にしたバリデーションが走ってしまうと、不要なエラーやセキュリティリスクの原因になります。

この記事では、Laravelにおける動的フォーム表示とバリデーションの両立方法について、安全かつ柔軟に実装するポイントを解説します。

動的フォームの典型例:条件付き入力

たとえば、「会社員」を選択した場合のみ「勤務先情報」欄を表示したいという場面を考えます。

HTML例(Blade)

<select name="job_status" id="job_status">
  <option value="freelance">フリーランス</option>
  <option value="employee">会社員</option>
</select>

<div id="company_fields" style="display: none;">
  <input type="text" name="company_name" placeholder="会社名">
  <input type="text" name="company_address" placeholder="住所">
</div>

JavaScript例(jQuery)

$('#job_status').on('change', function () {
  if ($(this).val() === 'employee') {
    $('#company_fields').show();
  } else {
    $('#company_fields').hide();
  }
});

FormRequestで条件付きバリデーションを実装

クライアントで非表示になっていても、ユーザーが改ざんして送信する可能性は常にあるため、サーバー側で確実に「必要なときだけバリデーションする」ロジックを組みます。

基本のFormRequestクラス

public function rules()
{
    $rules = [
        'job_status' => 'required|in:freelance,employee',
    ];

    if ($this->input('job_status') === 'employee') {
        $rules['company_name'] = 'required|string|max:255';
        $rules['company_address'] = 'required|string|max:255';
    }

    return $rules;
}

FormRequestは $this->input() を通じて、動的な入力値をもとにバリデーションルールを動的に切り替えることができます。

メッセージのカスタマイズ

public function messages()
{
    return [
        'company_name.required' => '会社名を入力してください',
        'company_address.required' => '会社住所を入力してください',
    ];
}

「表示されていないとき」は空データを送るようにする

非表示のフィールドが送信されないと、input()の戻り値が null になります。可能であれば、JavaScript側で空文字を送るようにしておくとバリデーションの安定性が増します。

if ($('#job_status').val() !== 'employee') {
  $('input[name="company_name"]').val('');
  $('input[name="company_address"]').val('');
}

または、サーバー側で prepareForValidation() を使って初期化することも可能です。

応用例:複数の条件が絡む入力欄

条件が複雑になる場合は、FormRequestクラスの中でロジックをメソッドに切り出して整理します。

protected function conditionalCompanyRules(): array
{
    if ($this->input('job_status') === 'employee') {
        return [
            'company_name' => 'required|string|max:255',
            'company_address' => 'required|string|max:255',
        ];
    }

    return [];
}

public function rules(): array
{
    return array_merge([
        'job_status' => 'required|in:freelance,employee',
    ], $this->conditionalCompanyRules());
}

セキュリティ観点からの注意点

  • クライアント側の「非表示」だけでは信頼しない(サーバーサイドで必ず条件判定)
  • 不要な入力欄はサニタイズ/マスアサインから除外$fillableなど)
  • ユーザーの状態(認証・権限)と連動した条件処理を明示的に書く

まとめ

Laravelで動的なフォーム表示とバリデーションを両立させるには、以下のポイントを意識する必要があります。

  • 表示条件に応じた FormRequest のルール定義
  • input()で動的な値をもとにバリデーション分岐
  • prepareForValidation() や空値送信で入力の一貫性を保つ

見た目に合わせてサーバー側のロジックも連動させることで、安全かつユーザーフレンドリーなフォームを構築することができます。