本文へ移動
Laravel Tips

バリデーション(入力のチェック)

送られてきた入力が正しいかを調べるバリデーションの使い方を、書き方・エラーの表示・フォームリクエスト・自作のルールまで説明します。

バリデーションは、送られてきた入力が正しいかを調べることです。たとえば「題名は必ず入れる」「メールアドレスの形になっている」といった決まりを、保存の前に確かめます。学校の提出物の、受付での「名前は書いてありますか」の確認のようなものです。

いちばんよく使うのは、リクエスト(ブラウザから届くお願い)の validate メソッドです。このページでは、ほかのやり方も説明します。確かめるための決まり(ルール)は種類が多いので、一覧は バリデーションのルール一覧にまとめてあります。値がほかと重ならないか(ユニークか)を、データベースで確かめるルールもあります。

まず動かしてみる#

フォームの入力を確かめて、エラーを画面に返すまでの流れを、ひととおり見てみます。

ルートを決める#

まず、routes/web.php に、次のルート(URL と、それを受け持つ処理を結びつけること)があるとします。

php
use App\Http\Controllers\PostController;

Route::get('/post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);

GET のルートは、新しいブログ記事を作るフォームを表示します。POST のルートは、新しい記事をデータベースに保存します。

コントローラーを作る#

次に、この2つのルートを受け持つコントローラー(リクエストを受けて、何を返すかを決めるクラス)です。store メソッドは、まず空にしておきます。

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PostController extends Controller
{
    /**
     * Show the form to create a new blog post.
     */
    public function create(): View
    {
        return view('post.create');
    }

    /**
     * Store a new blog post.
     */
    public function store(Request $request): RedirectResponse
    {
        // Validate and store the blog post...

        $post = /** ... */

        return to_route('post.show', ['post' => $post->id]);
    }
}

確かめる処理を書く#

store メソッドに、確かめる処理を書きます。Illuminate\Http\Request の validate メソッドを使います。決まりを守っていれば、そのまま次へ進みます。守っていなければ、Illuminate\Validation\ValidationException という例外(エラーの知らせ)が起き、エラーの答えが自動でユーザーに返されます。

ふつうの HTTP のリクエストで失敗したときは、前のページへ戻す答え(リダイレクト)が作られます。XHR リクエスト(JavaScript が、ページを切りかえずに送るリクエスト)のときは、エラーの文を入れた JSON の答えが返ります(後の「エラーの JSON」の節)。

php
/**
 * Store a new blog post.
 */
public function store(Request $request): RedirectResponse
{
    $validated = $request->validate([
        'title' => ['required', 'unique:posts', 'max:255'],
        'body' => ['required'],
    ]);

    // The blog post is valid...

    return redirect('/posts');
}

validate には、ルールを配列で渡します。使えるルールはルール一覧にあります。失敗したときは、答えが自動で作られ、通ったときは、コントローラーの処理が続きます。

validateWithBag を使うと、エラーを、名前を付けたエラーのまとまり(エラーバッグ)に入れられます。

php
$validated = $request->validateWithBag('post', [
    'title' => ['required', 'unique:posts', 'max:255'],
    'body' => ['required'],
]);

最初の失敗で止める#

1つの項目で、最初に失敗したら、それ以降のルールを確かめたくないときは、bail というルールを付けます。

php
$request->validate([
    'title' => ['bail', 'required', 'unique:posts', 'max:255'],
    'body' => ['required'],
]);

この例では、title の unique が失敗したら、max は確かめません。ルールは、並べた順に確かめられます。

入れ子の項目#

HTTP のリクエストに「入れ子」のデータ(author の中に name がある、など)が含まれるときは、ルールのキーを、ドット . でつなげて書きます。

php
$request->validate([
    'title' => ['required', 'unique:posts', 'max:255'],
    'author.name' => ['required'],
    'author.description' => ['required'],
]);

項目の名前に、本物のドットが含まれているときは、ドットの前にバックスラッシュを付けると、入れ子の意味にされません。

php
$request->validate([
    'title' => ['required', 'unique:posts', 'max:255'],
    'v1\.0' => ['required'],
]);

エラーを表示する#

入力がルールを守っていなかったら、どうなるでしょう。前に書いたとおり、Laravel は、ユーザーを前の場所へ戻します。同時に、すべてのエラーと入力した内容を、セッション(同じ人のアクセスをまたいで、少しの情報を覚えておくしくみ)に、1回だけ読める形で入れます。

$errors という変数が、すべてのビューで使えます。web ミドルウェアグループ(まとめてかかるミドルウェア)に入っている Illuminate\View\Middleware\ShareErrorsFromSession が、用意します。そのため、ビューで $errors は、いつもあるものとして使えます。$errors の中身は、Illuminate\Support\MessageBag というクラスのものです。使い方は、後の「エラーメッセージを扱う」の節です。

今の例では、失敗すると、ユーザーはコントローラーの create メソッドへ戻されます。ビューで、エラーを表示できます。

blade
<!-- /resources/views/post/create.blade.php -->

<h1>Create Post</h1>

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

<!-- Create Post Form -->

エラーの文を変える#

Laravel に入っているルールには、エラーの文が、lang/en/validation.php に書かれています。アプリに lang フォルダがなければ、lang:publish という Artisan コマンド(php artisan で動かすコマンド)で作れます。

lang/en/validation.php には、ルールごとの文があります。アプリに合わせて、自由に直せます。

このファイルを別の言語のフォルダにコピーすれば、エラーの文を、その言語に訳せます。多言語対応のくわしいことは、多言語対応のページにあります。

注意

新しい Laravel のアプリには、はじめは lang フォルダがありません。Laravel の言語ファイルを直したいときは、lang:publish コマンドで取り出します。

XHR リクエストの場合#

この例では、ふつうのフォームでデータを送りました。しかし、JavaScript で作った画面から、XHR リクエストで送るアプリも多くあります。XHR リクエストで validate を使ったときは、リダイレクトは作られません。代わりに、すべてのエラーを入れた JSON の答えが、HTTP のステータスコード 422 で返ります。

@error ディレクティブ#

Blade の @error ディレクティブ(@ で始まる命令)で、その項目にエラーがあるかを調べられます。中では $message で、エラーの文を表示できます。

blade
<!-- /resources/views/post/create.blade.php -->

<label for="title">Post Title</label>

<input
    id="title"
    type="text"
    name="title"
    class="@error('title') is-invalid @enderror"
/>

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

名前を付けたエラーバッグ(後の節)を使うときは、@error の2つ目の引数に、その名前を渡せます。

blade
<input ... class="@error('title', 'post') is-invalid @enderror">

フォームに入力を戻す#

バリデーションの失敗でリダイレクトするとき、Laravel は、リクエストの入力のすべてを、セッションに1回だけ読める形で入れます。次のリクエストで、その入力を取り出して、ユーザーが送ろうとしたフォームの中身を、元に戻せます。

前のリクエストの入力を取り出すには、Illuminate\Http\Request の old メソッドを呼びます。

php
$title = $request->old('title');

old という、どこからでも呼べる関数(ヘルパー関数)もあります。Blade のテンプレートで、元に戻すときは、これが便利です。その項目の古い入力が無いときは、null が返ります。

blade
<input type="text" name="title" value="{{ old('title') }}">

入れなくてもよい項目#

Laravel のアプリには、はじめから、グローバルミドルウェア(全部のリクエストにかかるミドルウェア)として、TrimStrings(文字の前後の空白を取る)と ConvertEmptyStringsToNull(空の文字を null にする)が入っています。そのため、空のまま送られた項目は null になります。入れなくてもよい項目には、nullable を付けてください。付けないと、null が間違いとして扱われます。

php
$request->validate([
    'title' => ['required', 'unique:posts', 'max:255'],
    'body' => ['required'],
    'publish_at' => ['nullable', 'date'],
]);

この例では、publish_at は、null か、正しい日付のどちらでもよい、と決めています。nullable が無いと、null は、正しくない日付として扱われます。

エラーの JSON#

ValidationException が起きたとき、リクエストが JSON の答えを求めていると、Laravel は、エラーの文を整えて、422 Unprocessable Entity の答えを返します。

次が、エラーの JSON の例です。入れ子のキーは、ドットでつないだ1つの名前になります。

json
{
    "message": "The team name field must be a string. (and 4 more errors)",
    "errors": {
        "team_name": [
            "The team name field must be a string.",
            "The team name field must be at least 1 characters."
        ],
        "authorization.role": [
            "The selected authorization.role is invalid."
        ],
        "users.0.email": [
            "The users.0.email field is required."
        ],
        "users.2.email": [
            "The users.2.email field must be a valid email address."
        ]
    }
}

フォームリクエストで確かめる#

込み入った確かめには、「フォームリクエスト」を作ります。フォームリクエストは、確かめる処理と、してよいかの確認(認可)を、中に持つリクエストのクラスです。make:request という Artisan コマンドで作ります。

bash
php artisan make:request StorePostRequest

作られたクラスは、app/Http/Requests に置かれます。そのフォルダがなければ、コマンドが作ります。できたクラスには、authorize と rules の2つのメソッドがあります。

authorize は、ログインしている人が、その操作をしてよいかを決めます。rules は、リクエストのデータに使うルールを返します。

php
/**
 * Get the validation rules that apply to the request.
 *
 * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
 */
public function rules(): array
{
    return [
        'title' => ['required', 'unique:posts', 'max:255'],
        'body' => ['required'],
    ];
}

補足

rules メソッドの引数に、必要な道具の型を書くと、サービスコンテナ(クラスを作って渡してくれる、道具箱のようなしくみ)が、自動で渡してくれます。

では、このルールはどうやって使われるのでしょう。コントローラーのメソッドの引数に、フォームリクエストの型を書くだけです。コントローラーのメソッドが動く前に、リクエストが確かめられます。そのため、コントローラーに確かめる処理を書かなくて済みます。

php
/**
 * Store a new blog post.
 */
public function store(StorePostRequest $request): RedirectResponse
{
    // The incoming request is valid...

    // Retrieve the validated input data...
    $validated = $request->validated();

    // Retrieve a portion of the validated input data...
    $validated = $request->safe()->only(['name', 'email']);
    $validated = $request->safe()->except(['name', 'email']);

    // Store the blog post...

    return redirect('/posts');
}

失敗したときは、ユーザーを前の場所へ戻す答えが作られます。エラーは、セッションに入れられ、表示できます。XHR リクエストのときは、ステータスコード 422 で、エラーの JSON が返ります。

補足

Inertia で作った Laravel の画面で、フォームリクエストのバリデーションを、入力しながらその場で確かめたいときは、Laravel Precognition という機能があります。

確かめたあとの追加の確認#

最初の確かめのあとに、さらに確かめたいことがあります。そのときは、フォームリクエストの after メソッドを使います。

after は、確かめが終わったあとに呼ばれる関数の配列を返します。関数は Illuminate\Validation\Validator を受け取り、必要ならエラーを足せます。

php
use Illuminate\Validation\Validator;

/**
 * Get the "after" validation callables for the request.
 */
public function after(): array
{
    return [
        function (Validator $validator) {
            if ($this->somethingElseIsInvalid()) {
                $validator->errors()->add(
                    'field',
                    'Something is wrong with this field!'
                );
            }
        }
    ];
}

after が返す配列には、__invoke メソッドを持つクラスも入れられます。__invoke は Validator を受け取ります。

php
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;
use Illuminate\Validation\Validator;

/**
 * Get the "after" validation callables for the request.
 */
public function after(): array
{
    return [
        new ValidateUserStatus,
        new ValidateShippingTime,
        function (Validator $validator) {
            //
        }
    ];
}

最初の失敗で、全体を止める#

リクエストのクラスに StopOnFirstFailure という PHP の属性(クラスの前に書く印)を付けると、1つでも失敗した時点で、ほかの項目の確かめも、すべて止まります。

php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\Attributes\StopOnFirstFailure;
use Illuminate\Foundation\Http\FormRequest;

#[StopOnFirstFailure]
class StorePostRequest extends FormRequest
{
    // ...
}

知らない項目を断る#

リクエストのクラスに FailOnUnknownFields を付けると、ルールに書いていない項目が送られてきたとき、はねつけます。

php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\Attributes\FailOnUnknownFields;
use Illuminate\Foundation\Http\FormRequest;

#[FailOnUnknownFields]
class StorePostRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title' => ['required', 'string'],
            'body' => ['required', 'string'],
        ];
    }
}

すべてのフォームリクエストに、まとめて効かせるには、AppServiceProvider で、次のように呼びます。

php
use Illuminate\Foundation\Http\FormRequest;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    FormRequest::failOnUnknownFields();
}

あるリクエストだけ、止めたいときは、属性に false を渡します。

php
#[FailOnUnknownFields(false)]
class PublicWebhookRequest extends FormRequest
{
    // ...
}

知らない項目をはねつけると、予想外の入力が、アプリの奥まで入りこむのを防げます。マスアサインメント(一括代入。配列でまとめて値を入れること)のような問題に対する、追加の守りになります。それでも、モデルの $fillable や $guarded を設定し、信頼できる、確かめずみの入力だけを保存してください。

戻す先を変える#

フォームリクエストの確かめに失敗すると、ふつうは、前の場所へ戻されます。この動きは変えられます。RedirectTo という属性で、戻す URL を決められます。

php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\Attributes\RedirectTo;
use Illuminate\Foundation\Http\FormRequest;

#[RedirectTo('/dashboard')]
class StorePostRequest extends FormRequest
{
    // ...
}

名前を付けたルートへ戻したいときは、RedirectToRoute を使います。

php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\Attributes\RedirectToRoute;
use Illuminate\Foundation\Http\FormRequest;

#[RedirectToRoute('dashboard')]
class StorePostRequest extends FormRequest
{
    // ...
}

エラーバッグを変える#

フォームリクエストが失敗すると、エラーは default というエラーバッグに入ります。別の名前のエラーバッグ(後の節)に入れたいときは、ErrorBag という属性を使います。

php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\Attributes\ErrorBag;
use Illuminate\Foundation\Http\FormRequest;

#[ErrorBag('login')]
class LoginRequest extends FormRequest
{
    // ...
}

フォームリクエストのクラスの属性をまとめると、次のとおりです。

属性 説明
StopOnFirstFailure 1つでも失敗したら、全体の確かめを止める
FailOnUnknownFields ルールにない項目が送られたら、はねつける(false を渡すと止められる)
RedirectTo 失敗したときに戻す URL を決める
RedirectToRoute 失敗したときに戻す、名前付きルートを決める
ErrorBag エラーを入れるエラーバッグの名前を決める

フォームリクエストの認可#

フォームリクエストには、authorize メソッドもあります。ここで、ログインしている人が、そのデータを直してよいかを決めます。たとえば、直そうとしているブログのコメントが、その人のものかを確かめられます。たいていは、ゲートとポリシー(「この人はこれをしてよいか」を決める関数とクラス)を使います。

php
use App\Models\Comment;

/**
 * Determine if the user is authorized to make this request.
 */
public function authorize(): bool
{
    $comment = Comment::find($this->route('comment'));

    return $comment && $this->user()->can('update', $comment);
}

フォームリクエストは、Laravel の基本のリクエストクラスを引きつぐので、user メソッドで、ログインしている人を取り出せます。route メソッドは、URL の中の {} で書いた部分(ルートのパラメータ)の値を取り出します。次の例の {comment} がそれです。

php
Route::post('/comment/{comment}');

ルートモデルバインディング(URL の値から、モデルを自動で探してくれる機能。ルーティングのページ)を使っていれば、探されたモデルを、リクエストのプロパティとして使えて、もっと短く書けます。

php
return $this->user()->can('update', $this->comment);

authorize が false を返すと、ステータスコード 403 の答えが自動で返り、コントローラーのメソッドは動きません。

認可を、アプリの別の場所で決めるなら、authorize を消すか、true を返すだけにできます。

php
/**
 * Determine if the user is authorized to make this request.
 */
public function authorize(): bool
{
    return true;
}

補足

authorize の引数にも、必要な道具の型を書けます。サービスコンテナが自動で渡します。

フォームリクエストのエラーの文#

messages メソッドを書きかえると、フォームリクエストが使うエラーの文を変えられます。「項目名.ルール名」と、その文の組を、配列で返します。

php
/**
 * Get the error messages for the defined validation rules.
 *
 * @return array<string, string>
 */
public function messages(): array
{
    return [
        'title.required' => 'A title is required',
        'body.required' => 'A message is required',
    ];
}

項目の名前を変える#

Laravel に入っているルールのエラーの文には、:attribute という置き場所(プレースホルダー)があります。そこへ入る項目の名前を変えたいときは、attributes メソッドを書きかえます。「項目 => 名前」の配列を返します。

php
/**
 * Get custom attributes for validator errors.
 *
 * @return array<string, string>
 */
public function attributes(): array
{
    return [
        'email' => 'email address',
    ];
}

確かめる前に入力を整える#

ルールを使う前に、リクエストのデータを整えたいときは、prepareForValidation メソッドを使います。

php
use Illuminate\Support\Str;

/**
 * Prepare the data for validation.
 */
protected function prepareForValidation(): void
{
    $this->merge([
        'slug' => Str::slug($this->slug),
    ]);
}

確かめたあとに、データを整えたいときは、passedValidation メソッドです。

php
/**
 * Handle a passed validation attempt.
 */
protected function passedValidation(): void
{
    $this->replace(['name' => 'Taylor']);
}

フォームリクエストのメソッドをまとめると、次のとおりです。

メソッド 説明
authorize その操作をしてよいかを決める
rules 使うルールを返す
after 確かめたあとの追加の確認を返す
messages エラーの文を変える
attributes :attribute に入る名前を変える
prepareForValidation 確かめる前に、データを整える
passedValidation 確かめたあとに、データを整える

自分で Validator を作る#

リクエストの validate を使いたくないときは、Validator ファサード(Route::get() のように、クラス名と :: で機能を呼べる窓口)の make メソッドで、確かめる係(バリデーター)を、自分で作れます。

php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class PostController extends Controller
{
    /**
     * Store a new blog post.
     */
    public function store(Request $request): RedirectResponse
    {
        $validator = Validator::make($request->all(), [
            'title' => ['required', 'unique:posts', 'max:255'],
            'body' => ['required'],
        ]);

        if ($validator->fails()) {
            return redirect('/post/create')
                ->withErrors($validator)
                ->withInput();
        }

        // Retrieve the validated input...
        $validated = $validator->validated();

        // Retrieve a portion of the validated input...
        $validated = $validator->safe()->only(['name', 'email']);
        $validated = $validator->safe()->except(['name', 'email']);

        // Store the blog post...

        return redirect('/posts');
    }
}

make の1つ目の引数は、確かめるデータ、2つ目は、使うルールの配列です。

失敗したかを調べたら、withErrors メソッドで、エラーをセッションに入れられます。そうすると、リダイレクトのあと、$errors が自動でビューに渡され、ユーザーに表示しやすくなります。withErrors には、バリデーター・MessageBag・PHP の配列のどれかを渡せます。

最初の失敗で止める#

stopOnFirstFailure メソッドを使うと、1つでも失敗した時点で、すべての項目の確かめを止めます。

php
if ($validator->stopOnFirstFailure()->fails()) {
    // ...
}

自動でリダイレクトする#

自分で作ったバリデーターでも、リクエストの validate のような自動のリダイレクトを使いたいときは、作ったバリデーターの validate メソッドを呼びます。失敗すると、自動でリダイレクトされ、XHR リクエストのときは、JSON の答えが返ります。

php
Validator::make($request->all(), [
    'title' => ['required', 'unique:posts', 'max:255'],
    'body' => ['required'],
])->validate();

失敗したとき、エラーを名前付きのエラーバッグに入れたいなら、validateWithBag を使います。

php
Validator::make($request->all(), [
    'title' => ['required', 'unique:posts', 'max:255'],
    'body' => ['required'],
])->validateWithBag('post');

名前付きのエラーバッグ#

1つのページに、フォームがいくつもあるときは、エラーをまとめた MessageBag に名前を付けると、フォームごとのエラーを取り出せます。withErrors の2つ目の引数に、名前を渡します。

php
return redirect('/register')->withErrors($validator, 'login');

名前を付けた MessageBag は、$errors の中から取り出せます。

blade
{{ $errors->login->first('email') }}

自分で作ったバリデーターのエラーの文#

Laravel が用意している文の代わりに、自分の文を使わせられます。いくつか方法があります。1つ目は、Validator::make の3つ目の引数に、文を渡す方法です。

php
$validator = Validator::make($input, $rules, $messages = [
    'required' => 'The :attribute field is required.',
]);

この例の :attribute は、確かめている項目の名前に置きかわります。ほかの置き場所も使えます。

php
$messages = [
    'same' => 'The :attribute and :other must match.',
    'size' => 'The :attribute must be exactly :size.',
    'between' => 'The :attribute value :input is not between :min - :max.',
    'in' => 'The :attribute must be one of the following types: :values',
];

項目ごとの文#

ある項目だけに、別の文を使いたいときは、ドットでつなぎます。項目の名前を先に書き、ルールの名前を続けます。

php
$messages = [
    'email.required' => 'We need to know your email address!',
];

項目の名前を変える#

エラーの文の :attribute を、別の名前にしたいときは、Validator::make の4つ目の引数に、名前の配列を渡します。

php
$validator = Validator::make($input, $rules, $messages, [
    'email' => 'email address',
]);

バリデーターで、あとから確かめる#

バリデーターにも after メソッドがあります。最初の確かめのあとに、追加で確かめられます。after は、関数か、関数の配列を受け取ります。関数は Illuminate\Validation\Validator を受け取り、エラーを足せます。

php
use Illuminate\Support\Facades\Validator;

$validator = Validator::make(/* ... */);

$validator->after(function ($validator) {
    if ($this->somethingElseIsInvalid()) {
        $validator->errors()->add(
            'field', 'Something is wrong with this field!'
        );
    }
});

if ($validator->fails()) {
    // ...
}

配列には、__invoke メソッドを持つクラスも入れられます。

php
use App\Validation\ValidateShippingTime;
use App\Validation\ValidateUserStatus;

$validator->after([
    new ValidateUserStatus,
    new ValidateShippingTime,
    function ($validator) {
        // ...
    },
]);

確かめた入力を取り出す#

フォームリクエストや、自分で作ったバリデーターで確かめたあと、実際に確かめられたデータだけを取り出したいことがあります。方法はいくつかあります。まず、validated メソッドです。確かめられたデータの配列が返ります。

php
$validated = $request->validated();

$validated = $validator->validated();

safe メソッドもあります。Illuminate\Support\ValidatedInput が返ります。only・except・all で、一部か全部を取り出せます。

php
$validated = $request->safe()->only(['name', 'email']);

$validated = $request->safe()->except(['name', 'email']);

$validated = $request->safe()->all();

ValidatedInput は、foreach でくり返したり、['email'] のように配列と同じ書き方で取り出したりもできます。

php
// Validated data may be iterated...
foreach ($request->safe() as $key => $value) {
    // ...
}

// Validated data may be accessed as an array...
$validated = $request->safe();

$email = $validated['email'];

確かめたデータへ、項目を足したいときは、merge です。

php
$validated = $request->safe()->merge(['name' => 'Taylor Otwell']);

確かめたデータをコレクション(配列を便利に扱うための入れ物)で取り出したいときは、collect です。

php
$collection = $request->safe()->collect();
メソッド 説明
validated 確かめられたデータの配列を返す
safe()->only 確かめられたデータから、指定した項目だけ取り出す
safe()->except 確かめられたデータから、指定した項目以外を取り出す
safe()->all 確かめられたデータを全部取り出す
safe()->merge 確かめられたデータへ、項目を足す
safe()->collect 確かめられたデータを、コレクションで取り出す

エラーメッセージを扱う#

バリデーターの errors メソッドを呼ぶと、Illuminate\Support\MessageBag が返ります。エラーの文を扱う、便利なメソッドがたくさんあります。すべてのビューで自動で使える $errors も、MessageBag です。

メソッド 説明
first 項目の最初のエラーの文を取り出す
get 項目のすべてのエラーの文を、配列で取り出す
all すべての項目のすべてのエラーの文を、配列で取り出す
has 項目にエラーの文があるかを調べる

項目の最初のエラーの文#

項目の最初のエラーの文は、first です。

php
$errors = $validator->errors();

echo $errors->first('email');

項目のすべてのエラーの文#

項目のすべてのエラーの文を配列で取り出すには、get です。

php
foreach ($errors->get('email') as $message) {
    // ...
}

配列の項目を確かめているときは、* を使って、配列の要素ごとのエラーの文をまとめて取り出せます。

php
foreach ($errors->get('attachments.*') as $message) {
    // ...
}

すべての項目のすべてのエラーの文#

すべての項目の、すべてのエラーの文を配列で取り出すには、all です。

php
foreach ($errors->all() as $message) {
    // ...
}

項目にエラーの文があるか#

has で、項目にエラーの文があるかを調べられます。

php
if ($errors->has('email')) {
    // ...
}

言語ファイルでエラーの文を決める#

Laravel に入っているルールには、エラーの文が、lang/en/validation.php に書かれています。アプリに lang フォルダがなければ、lang:publish コマンドで作れます。

ファイルには、ルールごとの文があります。アプリに合わせて、自由に直せます。別の言語のフォルダにコピーすれば、その言語に訳せます。くわしくは多言語対応のページです。

注意

新しい Laravel のアプリには、はじめは lang フォルダがありません。Laravel の言語ファイルを直したいときは、lang:publish コマンドで取り出します。

項目ごとの文#

項目とルールの組み合わせごとに、文を変えたいときは、lang/xx/validation.php の custom 配列に書きます。

php
'custom' => [
    'email' => [
        'required' => 'We need to know your email address!',
        'max' => 'Your email address is too long!'
    ],
],

言語ファイルで項目の名前を決める#

エラーの文の :attribute を、別の名前にしたいときは、lang/xx/validation.php の attributes 配列に書きます。

php
'attributes' => [
    'email' => 'email address',
],

注意

新しい Laravel のアプリには、はじめは lang フォルダがありません。Laravel の言語ファイルを直したいときは、lang:publish コマンドで取り出します。

言語ファイルで値の表し方を決める#

エラーの文には、:value という置き場所があり、その項目の今の値に置きかわります。この値を、別の分かりやすい表し方にしたいことがあります。たとえば、payment_type が cc のとき、クレジットカードの番号を必須にするルールです。

php
Validator::make($request->all(), [
    'credit_card_number' => ['required_if:payment_type,cc']
]);

このルールが失敗すると、次のエラーの文が出ます。

text
The credit card number field is required when payment type is cc.

cc ではなく、分かりやすい表し方にしたいときは、lang/xx/validation.php に values 配列を書きます。

php
'values' => [
    'payment_type' => [
        'cc' => 'credit card'
    ],
],

注意

新しい Laravel のアプリには、はじめは lang フォルダがありません。Laravel の言語ファイルを直したいときは、lang:publish コマンドで取り出します。

こう決めると、エラーの文は次のようになります。

text
The credit card number field is required when payment type is credit card.

言語ファイルの設定をまとめると、次のとおりです。

配列 説明
custom 項目とルールの組み合わせごとに、エラーの文を変える
attributes :attribute に入る名前を変える
values :value に入る値の表し方を変える

使えるルール#

ルールの一覧は、バリデーションのルール一覧のページにあります。

条件で、ルールを足す#

決まった値のときは確かめない#

ほかの項目が、ある値のときは、その項目を確かめたくないことがあります。exclude_if ルールを使います。次の例では、has_appointment が false のとき、appointment_date と doctor_name は確かめられません。

php
use Illuminate\Support\Facades\Validator;

$validator = Validator::make($data, [
    'has_appointment' => ['required', 'boolean'],
    'appointment_date' => ['exclude_if:has_appointment,false', 'required', 'date'],
    'doctor_name' => ['exclude_if:has_appointment,false', 'required', 'string'],
]);

反対に、ほかの項目が、ある値でないときは確かめない exclude_unless ルールもあります。

php
$validator = Validator::make($data, [
    'has_appointment' => ['required', 'boolean'],
    'appointment_date' => ['exclude_unless:has_appointment,true', 'required', 'date'],
    'doctor_name' => ['exclude_unless:has_appointment,true', 'required', 'string'],
]);

あるときだけ確かめる#

項目が、確かめるデータの中にあるときだけ、確かめたいことがあります。そのときは、sometimes ルールをルールの一覧に足します。

php
$validator = Validator::make($data, [
    'email' => ['sometimes', 'required', 'email'],
]);

この例では、email は、$data の配列にあるときだけ確かめられます。

補足

いつもあるはずで、空でもよい項目を確かめたいときは、前の「入れなくてもよい項目」の注意を見てください。

込み入った条件#

もっと込み入った条件で、ルールを足したいことがあります。たとえば、ほかの項目が 100 より大きいときだけ、ある項目を必須にしたい、といった場合です。まず、いつも変わらないルール(静的なルール)で、Validator を作ります。

php
use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
    'email' => ['required', 'email'],
    'games' => ['required', 'integer', 'min:0'],
]);

ゲームを集める人向けのアプリだとします。登録した人が 100 本以上のゲームを持っているなら、その理由を書いてもらいたい、と考えます。条件つきでこの決まりを足すには、Validator の sometimes メソッドを使います。

php
use Illuminate\Support\Fluent;

$validator->sometimes('reason', ['required', 'max:500'], function (Fluent $input) {
    return $input->games >= 100;
});

1つ目の引数は、条件つきで確かめる項目の名前、2つ目は、足したいルールの一覧です。3つ目の引数の関数が true を返すと、ルールが足されます。複数の項目を、まとめて決めることもできます。

php
$validator->sometimes(['reason', 'cost'], 'required', function (Fluent $input) {
    return $input->games >= 100;
});

補足

関数に渡される $input は、Illuminate\Support\Fluent です。確かめている入力やファイルを取り出せます。

込み入った、配列の条件#

同じ入れ子の配列の中の、ほかの項目の値で、確かめるかどうかを決めたいことがあります。でも、その配列が何番目かは分かりません。そういうときは、関数の2つ目の引数で、確かめている配列の1つ分を受け取れます。

php
$input = [
    'channels' => [
        [
            'type' => 'email',
            'address' => 'abigail@example.com',
        ],
        [
            'type' => 'url',
            'address' => 'https://example.com',
        ],
    ],
];

$validator->sometimes('channels.*.address', 'email', function (Fluent $input, Fluent $item) {
    return $item->type === 'email';
});

$validator->sometimes('channels.*.address', 'url', function (Fluent $input, Fluent $item) {
    return $item->type !== 'email';
});

$input と同じで、$item は、その項目のデータが配列のときは Illuminate\Support\Fluent です。そうでないときは、文字列です。

配列を確かめる#

ルール一覧の array ルールにあるとおり、array ルールには、使ってよいキーの一覧を渡せます。それ以外のキーが配列の中にあると、失敗します。

php
use Illuminate\Support\Facades\Validator;

$input = [
    'user' => [
        'name' => 'Taylor Otwell',
        'username' => 'taylorotwell',
        'admin' => true,
    ],
];

Validator::make($input, [
    'user' => ['array:name,username'],
]);

ふつうは、配列に入ってよいキーを、いつも書いておくべきです。書かないと、バリデーターの validate と validated が、ほかの入れ子のルールで確かめていないキーも含めて、配列全体を返してしまいます。

入れ子の配列の入力を確かめる#

入れ子になった配列の入力も、ドットでつなげて確かめられます。たとえば、HTTP のリクエストに photos[profile] という項目があるなら、次のように確かめます。

php
use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
    'photos.profile' => ['required', 'image'],
]);

配列の1つ1つを確かめることもできます。たとえば、配列で送られてきたメールアドレスが、どれもほかと重ならないことを確かめるには、次のように書きます。

php
$validator = Validator::make($request->all(), [
    'users.*.email' => ['email', 'unique:users'],
    'users.*.first_name' => ['required_with:users.*.last_name'],
]);

言語ファイルの項目ごとの文(前の「言語ファイルでエラーの文を決める」の節)にも * を使えます。配列の項目に、1つの文を使えます。

php
'custom' => [
    'users.*.email' => [
        'unique' => 'Each user must have a unique email address',
    ]
],

入れ子の配列のデータを使う#

ルールを決めるときに、入れ子の配列の、その要素の値を使いたいことがあります。そのときは Rule::forEach メソッドを使います。forEach には関数を渡します。この関数は、配列の要素ごとに呼ばれます。受け取るのは、その項目の値と、* を実際の番号に置きかえた項目の名前(companies.0.id など)です。そして、その要素に付けるルールの配列を返します。

php
use App\Rules\HasPermission;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

$validator = Validator::make($request->all(), [
    'companies.*.id' => Rule::forEach(function (string|null $value, string $attribute) {
        return [
            Rule::exists(Company::class, 'id'),
            new HasPermission('manage-company', $value),
        ];
    }),
]);

エラーの文の番号と位置#

配列を確かめるとき、失敗した要素の番号や位置を、エラーの文に入れたいことがあります。自分で決めるエラーの文に、:index(0 から数える)・:position(1 から数える)・:ordinal-position(1st のように数える)を入れられます。

php
use Illuminate\Support\Facades\Validator;

$input = [
    'photos' => [
        [
            'name' => 'BeachVacation.jpg',
            'description' => 'A photo of my beach vacation!',
        ],
        [
            'name' => 'GrandCanyon.jpg',
            'description' => '',
        ],
    ],
];

Validator::validate($input, [
    'photos.*.description' => ['required'],
], [
    'photos.*.description.required' => 'Please describe photo #:position.',
]);

この例は、確かめに失敗し、ユーザーには「Please describe photo #2.」というエラーの文が出ます。

さらに深い入れ子の番号や位置は、second-index・second-position・third-index・third-position のように使えます。

php
'photos.*.attributes.*.string' => 'Invalid attribute for photo #:second-position.',
置き場所 説明
:index 要素の番号(0 から数える)
:position 要素の位置(1 から数える)
:ordinal-position 要素の位置(1st のように数える)
second-index / second-position 2つ目の入れ子の番号/位置
third-index / third-position 3つ目の入れ子の番号/位置

ファイルを確かめる#

アップロードされたファイルを確かめるルールは、mimes・image・min・max など、たくさんあります。1つずつ書いてもよいのですが、Laravel には、メソッドをつなげて書ける、ファイル用のルールを作る道具(File)もあります。

php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\File;

Validator::validate($input, [
    'attachment' => [
        'required',
        File::types(['mp3', 'wav'])
            ->min(1024)
            ->max(12 * 1024),
    ],
]);

ファイルの種類を確かめる#

types メソッドには、拡張子(ファイル名の最後の .mp3 のような部分)だけを書きます。しかし、実際には、ファイルの中身を読んで MIME タイプ(ファイルの種類を表す名前)を推しはかり、それを確かめます。MIME タイプと拡張子の一覧は、次の場所にあります。

https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

ファイルの大きさを確かめる#

最小と最大の大きさは、単位を付けた文字列でも書けます。kb・mb・gb・tb が使えます。

php
File::types(['mp3', 'wav'])
    ->min('1kb')
    ->max('10mb');

画像ファイルを確かめる#

ユーザーが画像をアップロードするアプリでは、File の image メソッドで、画像かどうかを確かめられます(jpg・jpeg・png・bmp・gif・webp・avif・heic・heif)。

さらに、dimensions ルールで、画像の大きさを制限できます。

php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;

Validator::validate($input, [
    'photo' => [
        'required',
        File::image()
            ->min(1024)
            ->max(12 * 1024)
            ->dimensions(Rule::dimensions()->maxWidth(1000)->maxHeight(500)),
    ],
]);

補足

画像の大きさの確かめ方は、ルール一覧の dimensions に、くわしくあります。

注意

image ルールは、はじめは SVG ファイルを認めません。XSS(ほかの人が悪意のあるスクリプトを、ページに混ぜこむ攻撃)の危険があるからです。SVG を認めたいときは、allowSvg: true を渡します。File::image(allowSvg: true) のように書きます。

画像の大きさを確かめる#

画像の大きさ(幅と高さ)も確かめられます。たとえば、dimensions ルールで、幅が 1000 ピクセル以下、高さが 500 ピクセル以下かを確かめられます。

php
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\File;

File::image()->dimensions(
    Rule::dimensions()
        ->maxWidth(1000)
        ->maxHeight(500)
);

補足

画像の大きさの確かめ方は、ルール一覧の dimensions に、くわしくあります。

パスワードを確かめる#

パスワードが、十分に複雑かを確かめるには、Laravel の Password ルールのオブジェクトを使います。

php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;

$validator = Validator::make($request->all(), [
    'password' => ['required', 'confirmed', Password::min(8)],
]);

Password ルールでは、アプリに合わせて、パスワードの複雑さの条件を決められます。たとえば、文字・数字・記号を必ず含める、大文字と小文字を混ぜる、などです。

php
// Require at least 8 characters...
Password::min(8);

// Require at most 256 characters...
Password::min(16)->max(256);

// Require at least one letter...
Password::min(8)->letters();

// Require at least one uppercase and one lowercase letter...
Password::min(8)->mixedCase();

// Require at least one number...
Password::min(8)->numbers();

// Require at least one symbol...
Password::min(8)->symbols();

uncompromised メソッドを使うと、そのパスワードが、これまでの流出事件で外に漏れていないかも確かめられます。

php
Password::min(8)->uncompromised();

中では、k-匿名性(k-Anonymity。元のパスワードを知られないようにするしくみ)という方法で、haveibeenpwned.com のサービスに、漏れたことがあるかを問い合わせます。この方法なので、ユーザーのプライバシーや安全は守られます。

はじめは、流出したデータに、1回でも入っていれば、危ないパスワードとして扱われます。uncompromised の1つ目の引数で、その回数の目安を変えられます。

php
// Ensure the password appears no more than 3 times in the same data leak...
Password::min(8)->uncompromised(3);

もちろん、ここまでのメソッドは、全部つなげられます。

php
Password::min(8)
    ->max(256)
    ->letters()
    ->mixedCase()
    ->numbers()
    ->symbols()
    ->uncompromised();
メソッド 説明
min 最低の長さを決める
max 最大の長さを決める
letters 文字を、1つ以上含める
mixedCase 大文字と小文字を、それぞれ1つ以上含める
numbers 数字を、1つ以上含める
symbols 記号を、1つ以上含める
uncompromised 流出事件で漏れたことがないかを確かめる(引数で、入っていてよい回数を決められる)
rules 初期のパスワードのルールに、別のルールを足す
toPasswordRulesString HTML の passwordrules 属性に使える文字列にする

toPasswordRulesString メソッドで、Password ルールを、HTML の passwordrules 属性に使える文字列にできます。

blade
<input
    type="password"
    name="password"
    autocomplete="new-password"
    passwordrules="{{ Password::defaults()->toPasswordRulesString() }}"
/>

パスワードの初期のルールを決める#

アプリの1か所に、パスワードの初期のルールを決めておくと便利です。Password::defaults メソッドを使います。関数を受け取り、その関数が、初期の Password ルールを返します。ふつう、サービスプロバイダ(アプリの起動のときに、道具箱へ道具を登録する場所)の boot メソッドで呼びます。

php
use Illuminate\Validation\Rules\Password;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Password::defaults(function () {
        $rule = Password::min(8);

        return $this->app->isProduction()
            ? $rule->mixedCase()->uncompromised()
            : $rule;
    });
}

決めたあとは、パスワードにその初期のルールを使いたいとき、引数なしで defaults を呼びます。

php
'password' => ['required', Password::defaults()],

初期のルールに、別のルールを足したいときは、rules メソッドを使います。

php
use App\Rules\ZxcvbnRule;

Password::defaults(function () {
    $rule = Password::min(8)->rules([new ZxcvbnRule]);

    // ...
});

自分でルールを作る#

ルールのオブジェクトを使う#

Laravel には便利なルールがたくさんありますが、自分のルールを作りたいこともあります。方法の1つが、ルールのオブジェクトです。make:rule という Artisan コマンドで作れます。ここでは、文字が大文字かを確かめるルールを作ります。新しいルールは app/Rules に置かれます。そのフォルダがなければ、コマンドが作ります。

bash
php artisan make:rule Uppercase

作ったら、動きを書きます。ルールのオブジェクトには、validate というメソッドが1つあります。項目の名前・値・失敗したときに呼ぶ関数(エラーの文を渡す)を受け取ります。

php
<?php

namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;

class Uppercase implements ValidationRule
{
    /**
     * Run the validation rule.
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (strtoupper($value) !== $value) {
            $fail('The :attribute must be uppercase.');
        }
    }
}

ルールを作ったら、ほかのルールといっしょに、ルールのオブジェクトを渡します。

php
use App\Rules\Uppercase;

$request->validate([
    'name' => ['required', 'string', new Uppercase],
]);

エラーの文を訳す#

$fail に、決まった文を渡す代わりに、翻訳のキー(多言語対応)を渡して、Laravel に訳させることもできます。

php
if (strtoupper($value) !== $value) {
    $fail('validation.uppercase')->translate();
}

必要なら、translate の1つ目の引数に置きかえる値、2つ目の引数に言語を渡せます。

php
$fail('validation.location')->translate([
    'value' => $this->value,
], 'fr');

確かめているほかのデータを使う#

自分で作ったルールで、確かめているほかのデータもすべて使いたいときは、Illuminate\Contracts\Validation\DataAwareRule というインターフェース(守るべき決まりを書いたもの)を使います。クラスに setData メソッドが要ります。Laravel が、確かめを始める前に、確かめているデータ全部を渡して、自動で呼びます。

php
<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\DataAwareRule;
use Illuminate\Contracts\Validation\ValidationRule;

class Uppercase implements DataAwareRule, ValidationRule
{
    /**
     * All of the data under validation.
     *
     * @var array<string, mixed>
     */
    protected $data = [];

    // ...

    /**
     * Set the data under validation.
     *
     * @param  array<string, mixed>  $data
     */
    public function setData(array $data): static
    {
        $this->data = $data;

        return $this;
    }
}

確かめているバリデーターそのものが要るときは、ValidatorAwareRule を使います。

php
<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;
use Illuminate\Validation\Validator;

class Uppercase implements ValidationRule, ValidatorAwareRule
{
    /**
     * The validator instance.
     *
     * @var \Illuminate\Validation\Validator
     */
    protected $validator;

    // ...

    /**
     * Set the current validator.
     */
    public function setValidator(Validator $validator): static
    {
        $this->validator = $validator;

        return $this;
    }
}
インターフェース 説明
ValidationRule ルールのオブジェクトの基本。validate メソッドを持つ
DataAwareRule 確かめているデータ全部を受け取る(setData メソッド)
ValidatorAwareRule 確かめているバリデーターを受け取る(setValidator メソッド)

関数でルールを作る#

自分のルールを、アプリの中で1か所でしか使わないなら、ルールのオブジェクトの代わりに、関数が使えます。関数は、項目の名前・値・失敗したときに呼ぶ $fail を受け取ります。

php
use Illuminate\Support\Facades\Validator;
use Closure;

$validator = Validator::make($request->all(), [
    'title' => [
        'required',
        'max:255',
        function (string $attribute, mixed $value, Closure $fail) {
            if ($value === 'foo') {
                $fail("The {$attribute} is invalid.");
            }
        },
    ],
]);

空でも動くルール(暗黙のルール)#

はじめは、確かめる項目がない、または空の文字のときは、自分で作ったルールも含めて、ふつうのルールは動きません。たとえば、unique ルールは、空の文字には使われません。

php
use Illuminate\Support\Facades\Validator;

$rules = ['name' => ['unique:users,name']];

$input = ['name' => ''];

Validator::make($input, $rules)->passes(); // true

項目が空でも自分のルールを動かしたいときは、そのルールを「暗黙のルール」にします。暗黙のルールは、「この項目は必須だ」という意味を、口に出さずにふくんでいるルールです。作るには、make:rule に --implicit オプションを付けます。

bash
php artisan make:rule Uppercase --implicit

注意

暗黙のルールにしても、空の項目が自動で失敗になるわけではありません。項目が無いときや空のときに、本当に失敗にするかどうかは、ルールの中で自分で決めます。

関連するページ#

公式ドキュメント(英語)

2026年10月5日時点の内容をもとに、日本語でまとめています。

ページの一覧