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()
や空値送信で入力の一貫性を保つ
見た目に合わせてサーバー側のロジックも連動させることで、安全かつユーザーフレンドリーなフォームを構築することができます。