タイトル: 必須チェック
SEOタイトル: Laravel バリデーション required (必須チェック) 完全ガイド
| この記事の要点 |
|
required の基本
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|email',
'password' => 'required|min:8',
'age' => 'required|integer|min:0',
]);
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
// Controller の簡易記法
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
]);
User::create($validated);
}
required の判定基準
Laravel が「未入力」と判定するのは次のすべて:
| 値 | required で fail する? |
|---|---|
| null | fail |
空文字 "" | fail |
空配列 [] | fail |
| 未送信 (キー無し) | fail |
| UploadedFile でパス無し | fail |
| "0" (文字列ゼロ) | pass |
| 0 (数値ゼロ) | pass |
| false | pass |
| " " (空白のみ) | pass (空文字ではない) |
空白のみは pass するので、フォームで「未入力扱い」にしたいなら独自ルールが必要:
// 解決法 A: prepareForValidation で trim
class StoreUserRequest extends FormRequest
{
protected function prepareForValidation(): void
{
$this->merge([
'name' => trim($this->input('name', '')),
]);
}
public function rules(): array
{
return ['name' => 'required|string']; // trim 済みなので空白だけは required で fail
}
}
// 解決法 B: グローバルミドルウェアの TrimStrings (Laravel 標準で有効)
// app/Http/Kernel.php に \Illuminate\Foundation\Http\Middleware\TrimStrings::class
条件付き必須
required_if (他フィールドが特定値のとき必須)
// payment_method = 'card' のとき card_number 必須
$rules = [
'payment_method' => 'required|in:card,bank,cash',
'card_number' => 'required_if:payment_method,card|digits:16',
'bank_code' => 'required_if:payment_method,bank|digits:4',
];
// 複数値
'card_number' => 'required_if:payment_method,card,credit', // card OR credit
required_unless (他フィールドが特定値でなければ必須)
// status が 'draft' でなければ title が必須
$rules = [
'status' => 'required|in:draft,published',
'title' => 'required_unless:status,draft|string|max:255',
];
required_with / required_without
// other_name が入っていれば other_email も必須
'other_email' => 'required_with:other_name|email',
// すべて指定する場合
'other_email' => 'required_with_all:other_name,other_age|email',
// other_name が無ければ default_name 必須
'default_name' => 'required_without:other_name',
// すべて無ければ
'fallback' => 'required_without_all:a,b,c',
required_array_keys (配列の必須キー指定)
// address 配列に prefecture と city が必須
'address' => 'required|array|required_array_keys:prefecture,city',
'address.prefecture' => 'required|string',
'address.city' => 'required|string',
sometimes: キーが存在する時だけバリデーション
// 通常 required: キーが無いと fail
// sometimes: キーが無いとスキップ、あれば検証
$rules = [
'name' => 'sometimes|required|string', // 送られてきた時だけ必須
'email' => 'sometimes|email',
];
// 用途: PATCH (部分更新)
public function update(Request $request, User $user)
{
$validated = $request->validate([
'name' => 'sometimes|required|string|max:255',
'email' => 'sometimes|required|email|unique:users,email,' . $user->id,
'phone' => 'sometimes|nullable|string',
]);
$user->update($validated);
}
// Validator::sometimes() でクロージャ条件
$v = Validator::make($data, ['credit_limit' => 'numeric']);
$v->sometimes('credit_limit', 'required|min:0', function ($input) {
return $input->payment_method === 'credit';
});
nullable: 任意項目で null を許可
// nullable 無しで integer | null → fail (null は integer ではない)
// nullable 付ければ null を許可
$rules = [
'phone' => 'nullable|string|max:20',
'birthdate' => 'nullable|date',
'company_id' => 'nullable|integer|exists:companies,id',
];
Form Request クラスで整理
// php artisan make:request StoreUserRequest
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreUserRequest extends FormRequest
{
public function authorize(): bool
{
return $this->user()->can('create', User::class);
}
public function rules(): array
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|string|min:8|confirmed',
'role' => 'required|in:admin,user',
'company_id' => 'required_if:role,user|exists:companies,id',
'profile.bio' => 'nullable|string|max:1000',
'profile.avatar' => 'nullable|image|max:2048',
];
}
public function messages(): array
{
return [
'name.required' => 'お名前は必須です',
'email.required' => 'メールアドレスは必須です',
'email.email' => '有効なメールアドレスを入力してください',
'email.unique' => 'このメールアドレスは既に使用されています',
'password.min' => 'パスワードは:min文字以上で入力してください',
'password.confirmed' => 'パスワードが一致しません',
];
}
public function attributes(): array
{
return [
'name' => 'お名前',
'email' => 'メールアドレス',
];
}
}
// Controller では型ヒントするだけ
public function store(StoreUserRequest $request)
{
User::create($request->validated());
return redirect()->route('users.index');
}
required_array_keys と配列要素のバリデーション
// items が配列で各要素に name と price が必須
$rules = [
'items' => 'required|array|min:1',
'items.*.name' => 'required|string|max:255',
'items.*.price' => 'required|integer|min:0',
'items.*.tags' => 'nullable|array',
'items.*.tags.*' => 'string|max:20',
];
// 送信例
// items[0][name]=A&items[0][price]=100&items[1][name]=B&items[1][price]=200
カスタムメッセージ・属性名
$request->validate(
[
'name' => 'required|string|max:255',
'email' => 'required|email',
],
[
'name.required' => ':attribute を入力してください',
'email.required' => ':attribute を入力してください',
'email.email' => '正しい :attribute 形式で入力してください',
],
[
'name' => 'お名前',
'email' => 'メールアドレス',
]
);
// グローバルメッセージは resources/lang/ja/validation.php
// 'required' => ':attribute は必須項目です。',
JS バリデーションとの併用
クライアント JS で即時フィードバック、サーバで最終検証の二段構えが王道。サーバ側を省略してはいけません (DevTools で簡単に回避できる):
エラー表示
{{-- Blade --}}
@if ($errors->any())
@foreach ($errors->all() as $error)
- {{ $error }}
@endforeach
@endif
{{-- フィールド別 --}}
@error('name')
{{ $message }}
@enderror
{{-- API レスポンス (validate() が自動で 422 JSON 返す) --}}
{
"message": "The given data was invalid.",
"errors": {
"name": ["The name field is required."],
"email": ["The email field is required."]
}
}
FAQ
Q: required と present の違いは?
A: present はキーが存在することだけチェック (値が空文字でも OK)。required は値が「空でない」ことまで要求。
Q: チェックボックスの必須はどう書く?
A: 未チェックは送信されない (キー無し) ので required|accepted。accepted は値が yes / on / 1 / true / "1" のいずれかなら pass。
Q: ファイルアップロードの必須は?
A: 'avatar' => 'required|file|image|max:2048'。アップロード失敗 (サイズ超過等) も自動で fail します。