この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:atom
更新日時:2026-06-11 07:07:02

タイトル: 必須チェック
SEOタイトル: Laravel バリデーション required (必須チェック) 完全ガイド

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li>Laravel の必須チェックは <code>"name" => "required"</code> がベース</li><li>条件付き必須: <code>required_if</code> / <code>required_unless</code> / <code>required_with</code> / <code>required_without</code></li><li><code>sometimes</code> で<strong>キーが存在する時だけ</strong>バリデーション</li><li>empty 判定: <code>""</code> / null / <code>[]</code> / UploadedFile なし が「必須未入力」</li><li>クライアント JS バリデーション併用 + サーバ側必須チェックの<strong>二段構え</strong>が安全</li></ul></td></tr></table>
<h2>required の基本</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
    &apos;name&apos;     => &apos;required|string|max:255&apos;,
    &apos;email&apos;    => &apos;required|email&apos;,
    &apos;password&apos; => &apos;required|min:8&apos;,
    &apos;age&apos;      => &apos;required|integer|min:0&apos;,
]);

if ($validator->fails()) {
    return back()->withErrors($validator)->withInput();
}

// Controller の簡易記法
public function store(Request $request)
{
    $validated = $request->validate([
        &apos;name&apos;  => &apos;required|string|max:255&apos;,
        &apos;email&apos; => &apos;required|email|unique:users,email&apos;,
    ]);
    User::create($validated);
}</code></pre>
<h2>required の判定基準</h2>

<p>Laravel が「未入力」と判定するのは次のすべて:</p>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>値</th><th>required で fail する?</th></tr></thead>
<tbody>
<tr><td>null</td><td>fail</td></tr>
<tr><td>空文字 <code>""</code></td><td>fail</td></tr>
<tr><td>空配列 <code>[]</code></td><td>fail</td></tr>
<tr><td>未送信 (キー無し)</td><td>fail</td></tr>
<tr><td>UploadedFile でパス無し</td><td>fail</td></tr>
<tr><td>"0" (文字列ゼロ)</td><td>pass</td></tr>
<tr><td>0 (数値ゼロ)</td><td>pass</td></tr>
<tr><td>false</td><td>pass</td></tr>
<tr><td>"   " (空白のみ)</td><td>pass (空文字ではない)</td></tr>
</tbody>
</table>

<p><strong>空白のみは pass する</strong>ので、フォームで「未入力扱い」にしたいなら独自ルールが必要:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// 解決法 A: prepareForValidation で trim
class StoreUserRequest extends FormRequest
{
    protected function prepareForValidation(): void
    {
        $this->merge([
            &apos;name&apos; => trim($this->input(&apos;name&apos;, &apos;&apos;)),
        ]);
    }

    public function rules(): array
    {
        return [&apos;name&apos; => &apos;required|string&apos;];  // trim 済みなので空白だけは required で fail
    }
}

// 解決法 B: グローバルミドルウェアの TrimStrings (Laravel 標準で有効)
// app/Http/Kernel.php に \Illuminate\Foundation\Http\Middleware\TrimStrings::class</code></pre>
<h2>条件付き必須</h2>

<h3>required_if (他フィールドが特定値のとき必須)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// payment_method = &apos;card&apos; のとき card_number 必須
$rules = [
    &apos;payment_method&apos; => &apos;required|in:card,bank,cash&apos;,
    &apos;card_number&apos;    => &apos;required_if:payment_method,card|digits:16&apos;,
    &apos;bank_code&apos;      => &apos;required_if:payment_method,bank|digits:4&apos;,
];

// 複数値
&apos;card_number&apos; => &apos;required_if:payment_method,card,credit&apos;,  // card OR credit</code></pre>
<h3>required_unless (他フィールドが特定値でなければ必須)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// status が &apos;draft&apos; でなければ title が必須
$rules = [
    &apos;status&apos; => &apos;required|in:draft,published&apos;,
    &apos;title&apos;  => &apos;required_unless:status,draft|string|max:255&apos;,
];</code></pre>
<h3>required_with / required_without</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// other_name が入っていれば other_email も必須
&apos;other_email&apos; => &apos;required_with:other_name|email&apos;,

// すべて指定する場合
&apos;other_email&apos; => &apos;required_with_all:other_name,other_age|email&apos;,

// other_name が無ければ default_name 必須
&apos;default_name&apos; => &apos;required_without:other_name&apos;,

// すべて無ければ
&apos;fallback&apos; => &apos;required_without_all:a,b,c&apos;,</code></pre>
<h3>required_array_keys (配列の必須キー指定)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// address 配列に prefecture と city が必須
&apos;address&apos; => &apos;required|array|required_array_keys:prefecture,city&apos;,
&apos;address.prefecture&apos; => &apos;required|string&apos;,
&apos;address.city&apos;       => &apos;required|string&apos;,</code></pre>
<h2>sometimes: キーが存在する時だけバリデーション</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// 通常 required: キーが無いと fail
// sometimes: キーが無いとスキップ、あれば検証

$rules = [
    &apos;name&apos;  => &apos;sometimes|required|string&apos;,  // 送られてきた時だけ必須
    &apos;email&apos; => &apos;sometimes|email&apos;,
];

// 用途: PATCH (部分更新)
public function update(Request $request, User $user)
{
    $validated = $request->validate([
        &apos;name&apos;  => &apos;sometimes|required|string|max:255&apos;,
        &apos;email&apos; => &apos;sometimes|required|email|unique:users,email,&apos; . $user->id,
        &apos;phone&apos; => &apos;sometimes|nullable|string&apos;,
    ]);
    $user->update($validated);
}

// Validator::sometimes() でクロージャ条件
$v = Validator::make($data, [&apos;credit_limit&apos; => &apos;numeric&apos;]);
$v->sometimes(&apos;credit_limit&apos;, &apos;required|min:0&apos;, function ($input) {
    return $input->payment_method === &apos;credit&apos;;
});</code></pre>
<h2>nullable: 任意項目で null を許可</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// nullable 無しで integer | null → fail (null は integer ではない)
// nullable 付ければ null を許可

$rules = [
    &apos;phone&apos;      => &apos;nullable|string|max:20&apos;,
    &apos;birthdate&apos;  => &apos;nullable|date&apos;,
    &apos;company_id&apos; => &apos;nullable|integer|exists:companies,id&apos;,
];</code></pre>
<h2>Form Request クラスで整理</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// 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(&apos;create&apos;, User::class);
    }

    public function rules(): array
    {
        return [
            &apos;name&apos;           => &apos;required|string|max:255&apos;,
            &apos;email&apos;          => &apos;required|email|unique:users,email&apos;,
            &apos;password&apos;       => &apos;required|string|min:8|confirmed&apos;,
            &apos;role&apos;           => &apos;required|in:admin,user&apos;,
            &apos;company_id&apos;     => &apos;required_if:role,user|exists:companies,id&apos;,
            &apos;profile.bio&apos;    => &apos;nullable|string|max:1000&apos;,
            &apos;profile.avatar&apos; => &apos;nullable|image|max:2048&apos;,
        ];
    }

    public function messages(): array
    {
        return [
            &apos;name.required&apos;    => &apos;お名前は必須です&apos;,
            &apos;email.required&apos;   => &apos;メールアドレスは必須です&apos;,
            &apos;email.email&apos;      => &apos;有効なメールアドレスを入力してください&apos;,
            &apos;email.unique&apos;     => &apos;このメールアドレスは既に使用されています&apos;,
            &apos;password.min&apos;     => &apos;パスワードは:min文字以上で入力してください&apos;,
            &apos;password.confirmed&apos; => &apos;パスワードが一致しません&apos;,
        ];
    }

    public function attributes(): array
    {
        return [
            &apos;name&apos;  => &apos;お名前&apos;,
            &apos;email&apos; => &apos;メールアドレス&apos;,
        ];
    }
}

// Controller では型ヒントするだけ
public function store(StoreUserRequest $request)
{
    User::create($request->validated());
    return redirect()->route(&apos;users.index&apos;);
}</code></pre>
<h2>required_array_keys と配列要素のバリデーション</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// items が配列で各要素に name と price が必須
$rules = [
    &apos;items&apos;         => &apos;required|array|min:1&apos;,
    &apos;items.*.name&apos;  => &apos;required|string|max:255&apos;,
    &apos;items.*.price&apos; => &apos;required|integer|min:0&apos;,
    &apos;items.*.tags&apos;  => &apos;nullable|array&apos;,
    &apos;items.*.tags.*&apos; => &apos;string|max:20&apos;,
];

// 送信例
// items[0][name]=A&items[0][price]=100&items[1][name]=B&items[1][price]=200</code></pre>
<h2>カスタムメッセージ・属性名</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">$request->validate(
    [
        &apos;name&apos;  => &apos;required|string|max:255&apos;,
        &apos;email&apos; => &apos;required|email&apos;,
    ],
    [
        &apos;name.required&apos;  => &apos;:attribute を入力してください&apos;,
        &apos;email.required&apos; => &apos;:attribute を入力してください&apos;,
        &apos;email.email&apos;    => &apos;正しい :attribute 形式で入力してください&apos;,
    ],
    [
        &apos;name&apos;  => &apos;お名前&apos;,
        &apos;email&apos; => &apos;メールアドレス&apos;,
    ]
);

// グローバルメッセージは resources/lang/ja/validation.php
// &apos;required&apos; => &apos;:attribute は必須項目です。&apos;,</code></pre>
<h2>JS バリデーションとの併用</h2>

<p>クライアント JS で即時フィードバック、サーバで最終検証の<strong>二段構え</strong>が王道。サーバ側を省略してはいけません (DevTools で簡単に回避できる):</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><form action="/users" method="POST">
    @csrf
    <input type="text" name="name" required minlength="1" maxlength="255">
    <input type="email" name="email" required>
    <input type="password" name="password" required minlength="8">
    <button type="submit">送信</button>
</form></code></pre>
<h2>エラー表示</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">{{-- Blade --}}
@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

{{-- フィールド別 --}}
<input type="text" name="name" value="{{ old(&apos;name&apos;) }}"
       class="@error(&apos;name&apos;) is-invalid @enderror">
@error(&apos;name&apos;)
    <div class="text-danger">{{ $message }}</div>
@enderror

{{-- API レスポンス (validate() が自動で 422 JSON 返す) --}}
{
    "message": "The given data was invalid.",
    "errors": {
        "name": ["The name field is required."],
        "email": ["The email field is required."]
    }
}</code></pre>
<h2>FAQ</h2>

<p><strong>Q: <code>required</code> と <code>present</code> の違いは?</strong><br />
A: <code>present</code> はキーが存在することだけチェック (値が空文字でも OK)。<code>required</code> は値が「空でない」ことまで要求。</p>

<p><strong>Q: チェックボックスの必須はどう書く?</strong><br />
A: 未チェックは送信されない (キー無し) ので <code>required|accepted</code>。<code>accepted</code> は値が yes / on / 1 / true / "1" のいずれかなら pass。</p>

<p><strong>Q: ファイルアップロードの必須は?</strong><br />
A: <code>'avatar' => 'required|file|image|max:2048'</code>。アップロード失敗 (サイズ超過等) も自動で fail します。</p>