Skip to content

Latest commit

 

History

History
1945 lines (1346 loc) · 98 KB

validation.md

File metadata and controls

1945 lines (1346 loc) · 98 KB

バリデーション

イントロダクション

Laravelは、アプリケーションの受信データをバリデーションするために複数の異なるアプローチを提供します。すべての受信HTTPリクエストで使用可能なvalidateメソッドを使用するのがもっとも一般的です。しかし、バリデーションに対する他のアプローチについても説明します。

Laravelは、データに適用できる便利で数多くのバリデーションルールを持っており、特定のデータベーステーブルで値が一意であるかどうかをバリデーションする機能も提供します。Laravelのすべてのバリデーション機能に精通できるように、各バリデーションルールを詳しく説明します。

クイックスタート

Laravelの強力なバリデーション機能について学ぶため、フォームをバリデーションし、エラーメッセージをユーザーに表示する完全な例を見てみましょう。この高レベルの概要を読むことで、Laravelを使用して受信リクエストデータをバリデーションする一般的な方法を理解できます。

ルート定義

まず、routes/web.phpファイルに以下のルートを定義してあるとしましょう。

use App\Http\Controllers\PostController;

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

GETのルートは新しいブログポストを作成するフォームをユーザーへ表示し、POSTルートで新しいブログポストをデータベースへ保存します。

コントローラ作成

次に、これらのルートへの受信リクエストを処理する単純なコントローラを見てみましょう。今のところ、storeメソッドは空のままにしておきます。

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * 新ブログポスト作成フォームの表示
     *
     * @return \Illuminate\View\View
     */
    public function create()
    {
        return view('post.create');
    }

    /**
     * 新しいブログポストの保存
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        // ブログポストのバリデーションと保存コード…
    }
}

バリデーションロジック

これで、新しいブログ投稿をバリデーションするロジックをstoreメソッドに入力する準備が整いました。これを行うには、Illuminate\Http\Requestオブジェクトによって提供されるvalidateメソッドを使用します。バリデーションルールにパスすると、コードは正常に実行され続けます。しかし、バリデーションに失敗するとIlluminate\Validation\ValidationException例外が投げられ、適切なエラーレスポンスが自動的にユーザーに返送されます。

伝統的なHTTPリクエスト処理中にバリデーションが失敗した場合、直前のURLへのリダイレクトレスポンスが生成されます。受信リクエストがXHRリクエストの場合、バリデーションエラーメッセージを含むJSONレスポンスが返されます。

validateメソッドをもっとよく理解するため、storeメソッドに取り掛かりましょう。

/**
 * 新ブログポストの保存
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function store(Request $request)
{
    $validated = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    // ブログポストは有効
}

ご覧のとおり、バリデーションルールはvalidateメソッドへ渡されます。心配いりません。利用可能なすべてのバリデーションルールは文書化されています。この場合でもバリデーションが失敗したとき、適切な応答が自動的に生成されます。バリデーションにパスすると、コントローラは正常に実行を継続します。

もしくは、バリデーションルールを|で区切られた一つの文字列の代わりに、ルールの配列で指定することもできます。

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

さらに、validateWithBagメソッドを使用して、リクエストをバリデーションした結果のエラーメッセージをnamederrorbag内へ保存できます。

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

最初のバリデーション失敗時に停止

最初のバリデーションに失敗したら、残りのバリデーションルールの判定を停止したいことも、ときどきあります。このためには、bailルールを使ってください。

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

この例の場合、title属性のuniqueルールに失敗すると、maxルールはチェックされません。ルールは指定した順番にバリデートされます。

ネストした属性の注意点

受信HTTPリクエストに「ネストされた」フィールドデータが含まれている場合は、「ドット」構文を使用してバリデーションルールでこうしたフィールドを指定できます。

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

フィールド名にピリオドそのものが含まれている場合は、そのピリオドをバックスラッシュでエスケープし、「ドット」構文として解釈されることを明示的に防げます。

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

バリデーションエラー表示

では、受信リクエストフィールドが指定したバリデーションルールにパスしない場合はどうなるでしょうか。前述のように、Laravelはユーザーを直前の場所へ自動的にリダイレクトします。さらに、すべてのバリデーションエラーとリクエスト入力は自動的にセッションに一時保持保存されます。

$errors変数は、webミドルウェアグループが提供するIlluminate\View\Middleware\ShareErrorsFromSessionミドルウェアにより、アプリケーションのすべてのビューで共有されます。このミドルウェアが適用されると、ビューで$errors変数は常に定義され、$errors変数が常に使用可能になり、安全・便利に使用できると想定できます。$errors変数はIlluminate\Support\MessageBagのインスタンスです。このオブジェクトの操作の詳細は、ドキュメントを確認してください

この例では、バリデーションに失敗すると、エラーメッセージをビューで表示できるように、コントローラのcreateメソッドへリダイレクトされることになります。

<!-- /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

<!-- Postフォームの作成 -->

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

Laravelの組み込みバリデーションルールにはそれぞれエラーメッセージがあり、アプリケーションのresources/lang/en/validation.phpファイルに登録されています。このファイル内に、各バリデーションルールの翻訳エントリがあります。アプリケーションの要求に基づいて、これらのメッセージを自由に変更できます。

さらに、アプリケーションの言語へメッセージを翻訳するために、このファイルを別の翻訳言語ディレクトリにコピーできます。Laravelのローカリゼーションの詳細については、完全な多言語化ドキュメントをご覧ください。

XHRリクエストとバリデーション

この例では、従来のフォームを使用してデータをアプリケーションに送信しました。ただし、多くのアプリケーションは、JavaScriptを利用したフロントエンドからXHRリクエストを受信します。XHRリクエスト中にvalidateメソッドを使用すると、Laravelはリダイレクト応答を生成しません。代わりに、Laravelはすべてのバリデーションエラーを含むJSONレスポンスを生成します。このJSONレスポンスは、422 HTTPステータスコードとともに送信されます。

@errorディレクティブ

@errorBladeディレクティブを使用して、特定の属性にバリデーションエラーメッセージが存在するかどうかを簡単に判断できます。@errorディレクティブ内で、$message変数をエコーし​​てエラーメッセージを表示ができます。

<!-- /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引数へ渡せます。

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

フォームの再取得

Laravelがバリデーションエラーのためにリダイレクトレスポンスを生成するとき、フレームワークは自動的にセッションへのリクエストのすべての入力を一時保持保存します。これは、直後のリクエスト時、保存しておいた入力に簡単にアクセスし、ユーザーが送信しようとしたフォームを再入力・再表示できるようにします。

直前のリクエストから一時保持保存された入力を取得するには、Illuminate\Http\Requestのインスタンスでoldメソッドを呼び出します。oldメソッドは、直前に一時保持保存した入力データをsessionから取り出します。

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

Laravelはグローバルなoldヘルパも提供しています。Bladeテンプレート内に古い入力を表示している場合は、oldヘルパを使用してフォームを再入力・再表示する方が便利です。指定されたフィールドに古い入力が存在しない場合、nullが返されます。

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

オプションフィールドに対する注意

LaravelはTrimStringsConvertEmptyStringsToNullミドルウェアをアプリケーションのデフォルトグローバルミドルウェアスタックに含んでいます。これらのミドルウェアはApp\Http\Kernelクラスでリストされています。このため、バリデータがnull値を無効であると判定しないように、オプションフィールドへnullableを付ける必要が頻繁に起きるでしょう。

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

上記の例の場合、publish_atフィールドがnullか、有効な日付表現であることを指定しています。ルール定義にnullableが追加されないと、バリデータはnullを無効な日付として判定します。

フォームリクエストバリデーション

フォームリクエスト作成

より複雑なバリデーションシナリオの場合は、「フォームリクエスト」を作成することをお勧めします。フォームリクエストは、独自のバリデーションおよび認可ロジックをカプセル化するカスタムリクエストクラスです。フォームリクエストクラスを作成するには、make:request Artisan CLIコマンドを使用します。

php artisan make:request StorePostRequest

生成したフォームリクエストクラスは、app/Http/Requestsディレクトリに配置されます。このディレクトリが存在しない場合は、make:requestコマンドの実行時に作成されます。Laravelにより生成される各フォームリクエストには、authorizerulesの2つのメソッドがあります。

ご想像のとおり、authorizeメソッドは、現在認証されているユーザーがリクエストによって表されるアクションを実行できるかどうかを判断し、rulesメソッドはリクエスト中のデータを検証するバリデーションルールを返します。

/**
 * リクエストに適用するバリデーションルールを取得
 *
 * @return array
 */
public function rules()
{
    return [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ];
}

{tip} rulesメソッドの引数で必要な依存関係をタイプヒントにより指定することができます。それらはLaravelサービスコンテナを介して自動的に依存解決されます。

では、どのようにバリデーションルールを実行するのでしょうか?必要なのはコントローラのメソッドで、このリクエストをタイプヒントで指定することです。やって来たフォームリクエストはコントローラメソッドが呼び出される前にバリデーションを行います。つまり、コントローラでバリデーションロジックを取っ散らかす必要はありません。

/**
 * 新しいブログ投稿を保存
 *
 * @param  \App\Http\Requests\StorePostRequest  $request
 * @return Illuminate\Http\Response
 */
public function store(StorePostRequest $request)
{
    // 送信されたリクエストは正しい

    // バリデーション済みデータの取得
    $validated = $request->validated();

    // バリデーション済み入力データの一部を取得
    $validated = $request->safe()->only(['name', 'email']);
    $validated = $request->safe()->except(['name', 'email']);
}

バリデーションが失敗した場合、リダイレクトレスポンスが生成され、ユーザーを直前の場所に送り返します。エラーもセッ​​ションに一時保持され、表示できます。リクエストがXHRリクエストの場合、バリデーションエラーのJSON表現を含む422ステータスコードのHTTPレスポンスがユーザーに返されます。

フォームリクエストへのAfterフックを追加

フォームリクエストに"after"のバリデーションフックを追加する場合は、withValidatorメソッドを使用します。このメソッドは完全に構築されたバリデータを受け取り、バリデーションルールの実際の評価前に、メソッドのいずれでも呼び出せます。

/**
 * バリデータインスタンスの設定
 *
 * @param  \Illuminate\Validation\Validator  $validator
 * @return void
 */
public function withValidator($validator)
{
    $validator->after(function ($validator) {
        if ($this->somethingElseIsInvalid()) {
            $validator->errors()->add('field', 'Something is wrong with this field!');
        }
    });
}

最初のバリデーション失敗属性で停止

リクエストクラスにstopOnFirstFailureプロパティを追加することで、バリデーションの失敗が起きてすぐに、すべての属性のバリデーションを停止する必要があることをバリデータへ指示できます。

/**
 * バリデータが最初のルールの失敗で停​​止するかを指示
 *
 * @var bool
 */
protected $stopOnFirstFailure = true;

リダイレクト先のカスタマイズ

前述のとおり、フォームリクエストのバリデーションに失敗した場合、ユーザーを元の場所に戻すためのリダイレクトレスポンスが生成されます。しかし、この動作は自由にカスタマイズ可能です。それには、フォームのリクエストで、$redirectプロパティを定義します。

/**
 * バリデーション失敗時に、ユーザーをリダイレクトするURI
 *
 * @var string
 */
protected $redirect = '/dashboard';

または、ユーザーを名前付きルートへリダイレクトする場合は、$redirectRouteプロパティを代わりに定義します。

/**
 * バリデーション失敗時に、ユーザーをリダイレクトするルート
 *
 * @var string
 */
protected $redirectRoute = 'dashboard';

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

フォームリクエストクラスには、authorizeメソッドも含まれています。このメソッド内で、認証済みユーザーが特定のリソースを更新する権限を持っているかどうかを判別できます。たとえば、ユーザーが更新しようとしているブログコメントを実際に所有しているかどうかを判断できます。ほとんどの場合、次の方法で認可ゲートとポリシーを操作します。

use App\Models\Comment;

/**
 * ユーザーがこのリクエストの権限を持っているかを判断する
 *
 * @return bool
 */
public function authorize()
{
    $comment = Comment::find($this->route('comment'));

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

全フォームリクエストはLaravelのベースリクエストクラスを拡張していますので、現在認証済みユーザーへアクセスする、userメソッドが使えます。また、上記例中のrouteメソッドの呼び出しにも、注目してください。たとえば{comment}パラメーターのような、呼び出しているルートで定義してあるURIパラメータにもアクセスできます。

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

したがって、アプリケーションがルートモデル結合を利用している場合、解決されたモデルをリクエストのプロパティとしてアクセスすることで、コードをさらに簡潔にすることができます。

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

authorizeメソッドがfalseを返すと、403ステータスコードのHTTPレスポンスを自動的に返し、コントローラメソッドは実行しません。

アプリケーションの別の部分でリクエストの認可ロジックを処理する場合は、authorizeメソッドからtrueを返してください。

/**
 * ユーザーがこのリクエストの権限を持っているか判断
 *
 * @return bool
 */
public function authorize()
{
    return true;
}

{tip} authorizeメソッドの引数で、必要な依存をタイプヒントにより指定できます。それらはLaravelのサービスコンテナにより、自動的に依存解決されます。

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

フォームリクエストにより使用されているメッセージはmessageメソッドをオーバーライドすることによりカスタマイズできます。このメソッドから属性/ルールと対応するエラーメッセージのペアを配列で返してください。

/**
 * 定義済みバリデーションルールのエラーメッセージ取得
 *
 * @return array
 */
public function messages()
{
    return [
        'title.required' => 'A title is required',
        'body.required' => 'A message is required',
    ];
}

バリデーション属性のカスタマイズ

Laravelの組み込みバリデーションルールエラーメッセージの多くは、:attributeプレースホルダーを含んでいます。バリデーションメッセージの:attributeプレースホルダーをカスタム属性名に置き換えたい場合は、attributesメソッドをオーバーライドしてカスタム名を指定します。このメソッドは、属性と名前のペアの配列を返す必要があります。

/**
 * バリデーションエラーのカスタム属性の取得
 *
 * @return array
 */
public function attributes()
{
    return [
        'email' => 'email address',
    ];
}

検証のための入力準備

バリデーションルールを適用する前にリクエストからのデータを準備またはサニタイズする必要がある場合は、prepareForValidationメソッド使用します。

use Illuminate\Support\Str;

/**
 * バリーデーションのためにデータを準備
 *
 * @return void
 */
protected function prepareForValidation()
{
    $this->merge([
        'slug' => Str::slug($this->slug),
    ]);
}

バリデータの生成

リクエストのvalidateメソッドを使用したくない場合は、Validatorファサードを使用し、バリデータインスタンスを生成する必要があります。 このファサードのmakeメソッドで、新しいバリデータインスタンスを生成します。

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class PostController extends Controller
{
    /**
     * 新しいブログポストの保存
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);

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

        // バリデーション済みデータの取得
        $validated = $validator->validated();

        // バリデーション済みデータの一部を取得
        $validated = $validator->safe()->only(['name', 'email']);
        $validated = $validator->safe()->except(['name', 'email']);

        // ブログポストの保存処理…
    }
}

makeメソッドの第1引数は、バリデーションを行うデータです。第2引数はそのデータに適用するバリデーションルールの配列です。

リクエストのバリデーションが失敗したかどうかを判断した後、withErrorsメソッドを使用してエラーメッセージをセッションに一時保持保存できます。この方法を使用すると、リダイレクト後に$errors変数がビューと自動的に共有されるため、メッセージをユーザーへ簡単に表示できます。withErrorsメソッドは、バリデータ、MessageBag、またはPHPのarrayを引数に取ります。

最初のバリデート失敗時に停止

stopOnFirstFailureメソッドは、バリデーションが失敗したら、すぐにすべての属性のバリデーションを停止する必要があることをバリデータへ指示します。

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

自動リダイレクト

バリデータインスタンスを手動で作成するが、HTTPリクエストのvalidateメソッドによって提供される自動リダイレクトを利用したい場合は、既存のバリデータインスタンスでvalidateメソッドを呼び出すことができます。バリデーションが失敗した場合、ユーザーは自動的にリダイレクトされます。XHRリクエストの場合は、JSONレスポンスが返されます。

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

validateWithBagメソッドを使用しリクエストのバリデートを行った結果、失敗した場合に、エラーメッセージを名前付きエラーバッグへ保存することもできます。

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

名前付きエラーバッグ

1つのページに複数のフォームがある場合は、バリデーションエラーを含むMessageBagに名前を付けて、特定のフォームのエラーメッセージを取得可能にできます。これを実現するには、withErrorsの2番目の引数として名前を渡します。

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

$errors変数を使い、名前を付けたMessageBagインスタンスへアクセスできます。

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

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

必要に応じて、Laravelが提供するデフォルトのエラーメッセージの代わりにバリデータインスタンスが使用するカスタムエラーメッセージを指定できます。カスタムメッセージを指定する方法はいくつかあります。まず、カスタムメッセージをvalidator::makeメソッドに3番目の引数として渡す方法です。

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

この例の、:attributeプレースホルダーは、バリデーション中のフィールドの名前に置き換えられます。バリデーションメッセージには他のプレースホルダーも利用できます。例をご覧ください。

$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',
];

特定の属性に対するカスタムメッセージ指定

特定の属性に対してのみカスタムエラーメッセージを指定したい場合があります。「ドット」表記を使用してこれを行うことができます。最初に属性の名前を指定し、次にルールを指定します。

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

カスタム属性値の指定

Laravelの組み込みエラーメッセージの多くには、バリデーション中のフィールドや属性の名前に置き換えられる:attributeプレースホルダーが含まれています。特定のフィールドでこれらのプレースホルダーを置き換える値をカスタマイズするには、カスタム属性表示名の配列を4番目の引数としてValidator::makeメソッドに渡します。

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

バリデーション後のフック

バリデーションが完了した後に実行するコールバックを添付することもできます。これにより、追加のバリデーションを簡単に実行し、メッセージコレクションにエラーメッセージを追加することもできます。利用するには、バリデータインスタンスでafterメソッドを呼び出します。

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

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

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

バリデーション済み入力の利用

フォームのリクエストや手動で作成したバリデータのインスタンスを使って リクエストデータをバリデーションした後に、バリデーション済みの受信リクエストデータを取得したいと思われるかもしれません。これには方法がいくつかあります。まず、フォームのリクエストやバリデータインスタンスのvalidatedメソッドを呼び出す方法です。このメソッドは、バリデーション済みデータの配列を返します。

$validated = $request->validated();

$validated = $validator->validated();

他に、フォームリクエストやバリデータのインスタンスに対して、safeメソッドを呼び出すこともできます。このメソッドは、Illuminate\Support\ValidatedInputのインスタンスを返します。このオブジェクトはonlyexceptallメソッドを用意しており、バリデーション済みデータのサブセットや配列全体を取得できます。

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

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

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

さらに、Illuminate\Support\ValidatedInputインスタンスをループで配列のようにアクセスすることもできます。

// バリデーション済みデータをループ
foreach ($request->safe() as $key => $value) {
    //
}

// バリデーション済みデータを配列としてアクセス
$validated = $request->safe();

$email = $validated['email'];

バリデーション済みデータへさらにフィールドを追加したい場合は、mergeメソッドを呼び出します。

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

バリデーション済みデータをコレクションインスタンスとして取得したい場合は、collectメソッドを呼び出します。

$collection = $request->safe()->collect();

エラーメッセージの操作

Validatorインスタンスのerrorsメソッドを呼び出すと、エラーメッセージを操作する便利なメソッドを数揃えた、Illuminate\Support\MessageBagインスタンスを受け取ります。自動的に作成され、すべてのビューで使用できる$errors変数も、MessageBagクラスのインスタンスです。

指定フィールドの最初のエラーメッセージ取得

指定したフィールドの最初のエラーメッセージを取得するには、firstメソッドを使います。

$errors = $validator->errors();

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

指定フィールドの全エラーメッセージ取得

指定したフィールドの全エラーメッセージを配列で取得したい場合は、getメソッドを使います。

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

配列形式のフィールドをバリデーションする場合は、*文字を使用し、各配列要素の全メッセージを取得できます。

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

全フィールドの全エラーメッセージ取得

全フィールドの全メッセージの配列を取得したい場合は、allメソッドを使います。

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

指定フィールドのメッセージ存在確認

hasメソッドは、指定したフィールドのエラーメッセージが存在しているかを判定するために使います。

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

言語ファイルでのカスタムメッセージの指定

Laravelの各組み込みバリデーションルールには、アプリケーションのresources/lang/en/validation.phpファイルにエラーメッセージが用意されています。このファイル内に、各バリデーションルールの翻訳エントリがあります。アプリケーションのニーズに基づいて、これらのメッセージを自由に変更または変更できます。

さらに、このファイルを別の翻訳言語ディレクトリにコピーして、アプリケーションの言語のメッセージを翻訳できます。Laravelのローカリゼーションの詳細については、完全な多言語化ドキュメントをご覧ください。

特定の属性のカスタムメッセージ

アプリケーションのバリデーション言語ファイル内で、属性とルールの組み合わせを指定して、エラーメッセージをカスタマイズできます。これを行うには、カスタマイズメッセージをアプリケーションのresources/lang/xx/validation.php言語ファイルのcustom配列へ追加します。

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

言語ファイルでの属性の指定

Laravelの組み込みエラーメッセージの多くには、バリデーション中のフィールドまたは属性の名前に置き換えられる:attributeプレースホルダーが含まれています。バリデーションメッセージの:attribute部分をカスタム値に置き換えたい場合は、resources/lang/xx/validation.php言語ファイルのattributes配列でカスタム属性名を指定してください。

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

言語ファイルでの値の指定

Laravelの組み込みバリデーションルールエラーメッセージの一部には、リクエスト属性の現在の値に置き換えられる:valueプレースホルダーが含まれています。ただし、バリデーションメッセージの:value部分を値のカスタム表現へ置き換えたい場合があるでしょう。たとえば、payment_typeの値がccの場合にクレジットカード番号が必要であることを定義する次のルールについて考えてみます。

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

このバリデーションルールが通らない場合に、次のようなメッセージが表示されるとします。

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

支払いタイプの値としてccを表示する代わりに、values配列を定義することにより、resources/lang/xx/validation.php言語ファイルでよりユーザーフレンドリーな値表現が指定できます。

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

この値を定義したら、バリデーションルールは次のエラーメッセージを生成します。

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

使用可能なバリデーションルール

使用可能な全バリデーションルールとその機能の一覧です。

<style> .collection-method-list > p { column-count: 3; -moz-column-count: 3; -webkit-column-count: 3; column-gap: 2em; -moz-column-gap: 2em; -webkit-column-gap: 2em; } .collection-method-list a { display: block; } </style>

受け入れ 条件一致時受け入れ アクティブなURL (日付)より後 (日付)以降 アルファベット アルファベット記号 アルファベット数字 配列 継続終了 (日付)より前 (日付)以前 範囲 論理 確認 現在のパスワード 日付 同一日付 日付形式 拒否 条件一致時拒否 相違 桁指定数値 桁範囲指定数値 寸法(画像ファイル) 別々 メールアドレス 文字列終了 列挙型 除外 条件一致時フィールド除外 条件不一致時フィールド除外 不在時フィールド除外 存在(データベース) ファイル 充満 より大きい 以上 画像(ファイル) 内包 配列内 整数 IPアドレス MACアドレス JSON より小さい 以下 最大値 MIMEタイプ MIMEタイプ(ファイル拡張子) 最小値 倍数値 非内包 正規表現不一致 NULL許可 数値 パスワード 存在 禁止 禁止If 禁止Unless 他フィールド禁止 正規表現 必須 指定フィールド値一致時必須 指定フィールド値非一致時必須 指定フィールド存在時必須 全指定フィールド存在時必須 指定フィールド非存在時必須 全指定フィールド非存在時必須 同一 サイズ 存在時バリデート実行 文字列開始 文字列 タイムゾーン 一意(データベース) URL UUID

accepted

フィールドが、"yes""on"1、またはtrueであることをバリデートします。これは、「利用規約」の承認または同様のフィールドをバリデーションするのに役立ちます。

accepted_if:他のフィールド,値,...

他のフィールドが指定した値と等しい場合、このフィールドは "yes""on"1trueであることをバリデートします。これは、"Terms of Service "の了承や似たようなフィールドをバリデートするのに便利です。

active_url

フィールドが、dns_get_record PHP関数により、有効なAかAAAAレコードであることをバリデートします。dns_get_recordへ渡す前に、parse_url PHP関数により指定したURLのホスト名を切り出します。

after:日付

フィールドは、指定された日付以降の値であることをバリデートします。日付を有効なDateTimeインスタンスに変換するため、strtotimePHP関数に渡します。

'start_date' => 'required|date|after:tomorrow'

strtotimeにより評価される日付文字列を渡す代わりに、その日付と比較する他のフィールドを指定することもできます。

'finish_date' => 'required|date|after:start_date'

after_or_equal:日付

フィールドが指定した日付以降であることをバリデートします。詳細はafterルールを参照してください。

alpha

フィールドが全部アルファベット文字であることをバリデートします。

alpha_dash

フィールドが全部アルファベット文字と数字、ダッシュ(-)、下線(_)であることをバリデートします。

alpha_num

フィールドが全部アルファベット文字と数字であることをバリデートします。

array

フィールドがPHPの配列タイプであることをバリデートします。

arrayルールに追加の値を指定する場合、入力配列の各キーは、ルールに指定した値のリスト内に存在する必要があります。次の例では、入力配列のadminキーは、arrayルールにした値のリストに含まれていないので、無効です。

use Illuminate\Support\Facades\Validator;

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

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

一般的に、配列内に存在することが許される配列キーを常に指定する必要があります。そうしないと、バリデータのvalidatevalidatedメソッドは他のネストした配列バリデーションルールにより検証されていなくても、配列とそのすべてのキーを含むバリデーション済みデータをすべて返してしまうことになります。

必要に応じ、許可するキーのリストを指定せずにarrayルールを使用した場合でも、Laravelのバリデータが返す「検証済み」データに未検証の配列キーを含めないように指示できます。そうするには、アプリケーションのAppServiceProviderbootメソッドでバリデータのexcludeUnvalidatedArrayKeysメソッドを呼び出してください。それによりバリデータは、ネストする配列ルールにより検証された場合にのみ返される「検証済み」データへ配列キーを含めます。

use Illuminate\Support\Facades\Validator;

/**
 * 全アプリケーションサービスの登録
 *
 * @return void
 */
public function boot()
{
    Validator::excludeUnvalidatedArrayKeys();
}

bail

フィールドでバリデーションにはじめて失敗した時点で、残りのルールのバリデーションを中止します。

bailルールはバリデーションが失敗したときに、特定のフィールドのバリデーションのみを停止するだけで、一方のstopOnFirstFailureメソッドは、ひとつバリデーション失敗が発生したら、すべての属性のバリデーションを停止する必要があることをバリデータに指示します。

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

before:日付

フィールドは、指定された日付より前の値であることをバリデートします。日付を有効なDateTimeインスタンスへ変換するために、PHPのstrtotime関数へ渡します。さらに、afterルールと同様に、バリデーション中の別のフィールドの名前をdateの値として指定できます。

before_or_equal:日付

フィールドは、指定された日付より前または同じ値であることをバリデートします。日付を有効なDateTimeインスタンスへ変換するために、PHPのstrtotime関数へ渡します。さらに、afterルールと同様に、バリデーション中の別のフィールドの名前をdateの値として指定できます。

between:min,max

フィールドが指定された最小値最大値の間のサイズであることをバリデートします。sizeルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。

boolean

フィールドが論理値として有効であることをバリデートします。受け入れられる入力は、truefalse10"1""0"です。

confirmed

フィールドが、{field}_confirmationフィールドと一致する必要があります。たとえば、バリデーション中のフィールドが「password」の場合、「password_confirmation」フィールドが入力に存在し一致している必要があります。

current_password

フィールドが、認証されているユーザーのパスワードと一致することをバリデートします。ルールの最初のパラメータで、認証ガードを指定できます。

'password' => 'current_password:api'

date

パリデーションされる値はPHP関数のstrtotimeにより、有効で相対日付ではないことをバリデートします。

date_equals:日付

フィールドが、指定した日付と同じことをバリデートします。日付を有効なDateTimeインスタンスに変換するために、PHPのstrtotime関数へ渡します。

date_format:フォーマット

バリデーションされる値がフォーマット定義と一致するか確認します。バリデーション時にはdatedate_formatどちらかを使用しなくてはならず、両方はできません。このバリデーションはPHPのDateTimeクラスがサポートするフォーマットをすべてサポートしています。

declined

フィールドが"no""off"0falseであることをバリデートします。

declined_if:他のフィールド,値,...

他のフィールドが指定した値と等しい場合、このフィールドは"no", "off", 0, or falseであることをバリデートします。

different:フィールド

フィールドが指定されたフィールドと異なった値を指定されていることをバリデートします。

digits:

フィールドが数値で、の桁数であることをバリデートします。

digits_between:最小値,最大値

フィールドが整数で、桁数が最小値から最大値の間であることをバリデートします。

dimensions

バリデーション対象のファイルが、パラメータにより指定されたサイズに合致することをバリデートします。

'avatar' => 'dimensions:min_width=100,min_height=200'

使用可能なパラメータは、min_widthmax_widthmin_heightmax_heightwidth__heightratioです。

**ratio**制約は、幅を高さで割ったものとして表す必要があります。これは、3/2のような分数または1.5のようなfloatのいずれかで指定します。

'avatar' => 'dimensions:ratio=3/2'

このルールは多くの引数を要求するので、Rule::dimensionsメソッドを使い、記述的にこのルールを構築してください。

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'avatar' => [
        'required',
        Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
    ],
]);

distinct

配列のバリデーション時、フィールドに重複した値がないことをバリデートします。

'foo.*.id' => 'distinct'

distinctはデフォルトで緩い比較を使用します。厳密な比較を使用するには、検証ルール定義にstrictパラメータを追加することができます。

'foo.*.id' => 'distinct:strict'

バリデーションルールの引数にignore_caseを追加して、大文字と小文字の違いを無視するルールを加えられます。

'foo.*.id' => 'distinct:ignore_case'

email

バリデーション中のフィールドは、電子メールアドレスのフォーマットである必要があります。このバリデーションルールは、egulias/email-validatorパッケージを使用して電子メールアドレスをバリデーションします。デフォルトではRFCValidationバリデータが適用されますが、他のバリデーションスタイルを適用することもできます。

'email' => 'email:rfc,dns'

上記の例では、RFCValidationDNSCheckValidationバリデーションを適用しています。適用可能なバリデーションスタイルは、次の通りです。

  • rfc: RFCValidation
  • strict: NoRFCWarningsValidation
  • dns: DNSCheckValidation
  • spoof: SpoofCheckValidation
  • filter: FilterEmailValidation

PHPのfilter_var関数を使用するfilterバリデータは、Laravelに付属しており、Laravelバージョン5.8より前のLaravelのデフォルトの電子メールバリデーション動作でした。

{note} dnsおよびspoofバリデータには、PHPのintl拡張が必要です。

ends_with:foo,bar,...

フィールドの値が、指定された値で終わることをバリデートします。

enum

Enumルールはクラスベースのルールで、対象のフィールドに有効なenumの値が含まれているかどうかをバリデートします。Enumルールは、コンストラクタの引数に唯一、enumの名前を取ります。

use App\Enums\ServerStatus;
use Illuminate\Validation\Rules\Enum;

$request->validate([
    'status' => [new Enum(ServerStatus::class)],
]);

{note} Enumは、PHPバージョン8.1以上でのみ使用可能です。

exclude

フィルードの値がvalidatevalidatedメソッドが返すリクエストデータから除外されていることをバリデートします。

exclude_if:他のフィールド,

他のフィールドと等しい場合、validatevalidatedメソッドが返すリクエストデータから、バリデーション指定下のフィールドが除外されます。

exclude_unless:他のフィールド,

他のフィールドと等しくない場合、validatevalidatedメソッドが返すリクエストデータから、バリデーション指定下のフィールドが除外されます。もしnullexclude_unless:name,null)の場合は、比較フィールドがnullであるか、比較フィールドがリクエストデータに含まれていない限り、バリデーション指定下のフィールドは除外されます。

exclude_without:他のフィールド

他のフィールドが存在しない場合、validatevalidatedメソッドが返すリクエストデータから、バリデーション指定下のフィールドが除外されます。

exists:テーブル,カラム

フィールドは、指定のデータベーステーブルに存在する必要があります。

基本的なExistsルールの使用法

'state' => 'exists:states'

columnオプションが指定されていない場合、フィールド名が使用されます。したがって、この場合、ルールは、statesデータベーステーブルに、リクエストのstate属性値と一致するstateカラム値を持つレコードが含まれていることをバリデーションします。

カスタムカラム名の指定

データベーステーブル名の後に配置することで、バリデーションルールで使用するデータベースカラム名を明示的に指定できます。

'state' => 'exists:states,abbreviation'

場合によっては、existsクエリに使用する特定のデータベース接続を指定する必要があります。これは、接続名をテーブル名の前に付けることで実現できます。

'email' => 'exists:connection.staff,email'

テーブル名を直接指定する代わりに、Eloquentモデルを指定することもできます。

'user_id' => 'exists:App\Models\User,id'

バリデーションルールで実行されるクエリをカスタマイズしたい場合は、ルールをスラスラと定義できるRuleクラスを使ってください。下の例では、|文字を区切りとして使用する代わりに、バリデーションルールを配列として指定しています。

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::exists('staff')->where(function ($query) {
            return $query->where('account_id', 1);
        }),
    ],
]);

file

フィールドがアップロードに成功したファイルであることをバリデートします。

filled

フィールドが存在する場合、空でないことをバリデートします。

gt:field

フィールドが指定したフィールドより大きいことをバリデートします。2つのフィールドは同じタイプでなくてはなりません。文字列、数値、配列、ファイルは、sizeルールと同じ規約により評価します。

gte:field

フィールドが指定したフィールド以上であることをバリデートします。2つのフィールドは同じタイプでなくてはなりません。文字列、数値、配列、ファイルは、sizeルールと同じ規約により評価します。

image

ファイルは画像(jpg、jpeg、png、bmp、gif、svg、webp)である必要があります。

in:foo,bar...

フィールドが指定したリストの中の値に含まれていることをバリデートします。このルールを使用するために配列をimplodeする必要が多くなりますので、ルールを記述的に構築するには、Rule::inメソッドを使ってください。

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'zones' => [
        'required',
        Rule::in(['first-zone', 'second-zone']),
    ],
]);

inルールとarrayルールを組み合わせた場合、入力配列の各値は、inルールに指定した値のリスト内に存在しなければなりません。次の例では,入力配列中のLAS空港コードは,inルールへ指定した空港のリストに含まれていないため無効です。

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

$input = [
    'airports' => ['NYC', 'LAS'],
];

Validator::make($input, [
    'airports' => [
        'required',
        'array',
        Rule::in(['NYC', 'LIT']),
    ],
]);

in_array:他のフィールド.*

フィールドが、他のフィールドの値のどれかであることをバリデートします。

integer

フィールドが整数値であることをバリデートします。

{note} このバリデーションルールは、入力が「整数」変数タイプであるか確認しません。入力がPHPのFILTER_VALIDATE_INTルールで受け入れられるか検証するだけです。入力を数値として検証する必要がある場合は、このルールをnumericバリデーションルールと組み合わせて使用​​してください。

ip

フィールドがIPアドレスの形式として正しいことをバリデートします。

ipv4

フィールドがIPv4アドレスの形式として正しいことをバリデートします。

ipv6

フィールドがIPv6アドレスの形式として正しいことをバリデートします。

mac_address

フィールドがMACアドレスとして正しいことをバリデートします。

json

フィールドが有効なJSON文字列であることをバリデートします。

lt:field

フィールドが指定したフィールドより小さいことをバリデートします。2つのフィールドは同じタイプでなくてはなりません。文字列、数値、配列、ファイルは、sizeルールと同じ規約により評価します。

lte:field

フィールドが指定したフィールド以下であることをバリデートします。2つのフィールドは同じタイプでなくてはなりません。文字列、数値、配列、ファイルは、sizeルールと同じ規約により評価します。

max:

フィールドが最大値として指定された以下であることをバリデートします。sizeルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。

mimetypes:text/plain,...

フィールドが指定されたMIMEタイプのどれかであることをバリデートします。

'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime'

アップロードしたファイルのMIMEタイプを判別するために、ファイルの内容が読み取られ、フレームワークはMIMEタイプを推測します。これは、クライアントが提供するMIMEタイプとは異なる場合があります。

mimes:foo,bar,...

フィールドで指定されたファイルが拡張子のリストの中のMIMEタイプのどれかと一致することをバリデートします。

MIMEルールの基本的な使用法

'photo' => 'mimes:jpg,bmp,png'

拡張子を指定するだけでもよいのですが、このルールは実際には、ファイルの内容を読み取ってそのMIMEタイプを推測することにより、ファイルのMIMEタイプをバリデーションします。MIMEタイプとそれに対応する拡張子の完全なリストは、次の場所にあります。

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

min:

フィールドが最小値として指定された以上であることをバリデートします。sizeルールと同様の判定方法で、文字列、数値、配列、ファイルが評価されます。

multiple_of:

フィールドが、の倍数であることをバリデートします。

{note} multiple_of ルールを使用するには、bcmath PHP 拡張機能が必要です。

not_in:foo,bar,...

フィールドが指定された値のリスト中に含まれていないことをバリデートします。Rule::notInメソッドのほうが、ルールの構成が読み書きしやすいでしょう。

use Illuminate\Validation\Rule;

Validator::make($data, [
    'toppings' => [
        'required',
        Rule::notIn(['sprinkles', 'cherries']),
    ],
]);

not_regex:正規表現

フィールドが指定した正規表現と一致しないことをバリデートします。

このルールは内部でPHPのpreg_match関数を使用しています。パターンは有効なデリミタを使用していることも含め、preg_matchが求めているフォーマットにしたがって指定する必要があります。たとえば:'email' => 'not_regex:/^.+$/i'

{note} regexnot_regexパターンを使用するとき、特に正規表現に|文字が含まれている場合は、|区切り文字を使用する代わりに配列を使用してバリデーションルールを指定する必要があります。

nullable

フィールドはnullであることを許容します。

numeric

フィールドは数値であることをバリデートします。

password

フィールドは、認証済みユーザーのパスワードと一致する必要があります。

{note} このルールはLaravel9で削除するため、current_passwordへ名前を変更しました。代わりに現在のパスワードルールを使用してください。

present

フィールドが存在していることをバリデートしますが、存在していれば空を許します。

prohibited

フィールドが空であるか、存在していないことをバリデートします。

prohibited_if:anotherfield,value,...

anotherfieldフィールドが任意のvalueと等しい場合、対象のフィールドは空であるか、存在しないことをバリデートします。

prohibited_unless:anotherfield,value,...

anotherfielフィールドが任意のvalueと等しくない場合、対象のフィールドは空であるか、存在していないことをバリデートします。

prohibits:anotherfield,...

フィールドが存在する場合、anotherfieldで指定したフィールドが、たとえ空であっても1つも存在していないことをバリデートします。

regex:正規表現

フィールドが指定された正規表現にマッチすることをバリデートします。

このルールは内部でPHPのpreg_match関数を使用しています。パターンは有効なデリミタを使用していることも含め、preg_matchが求めているフォーマットにしたがって指定する必要があります。たとえば:'email' => 'regex:/^.+@.+$/i'

{note} regexnot_regexパターンを使用するとき、特に正規表現に|文字が含まれている場合は、|区切り文字を使用する代わりに、配列でルールを指定する必要があります。

required

フィールドが入力データに存在しており、かつ空でないことをバリデートします。フィールドは以下の条件の場合、「空」であると判断されます。

  • 値がnullである。
  • 値が空文字列である。
  • 値が空の配列か、空のCountableオブジェクトである。
  • 値がパスのないアップロード済みファイルである。

required_if:他のフィールド,,...

他のフィールドのどれかと一致している場合、このフィールドが存在し、かつ空でないことをバリデートします。

required_ifルールのより複雑な条件を作成したい場合は、Rule::requiredIfメソッドを使用できます。このメソッドは、ブール値またはクロージャを受け入れます。クロージャが渡されると、クロージャは「true」または「false」を返し、バリデーション中のフィールドが必要かどうかを示します。

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($request->all(), [
    'role_id' => Rule::requiredIf($request->user()->is_admin),
]);

Validator::make($request->all(), [
    'role_id' => Rule::requiredIf(function () use ($request) {
        return $request->user()->is_admin;
    }),
]);

required_unless:他のフィールド,,...

他のフィールドのどれとも一致していない場合、このフィールドが存在し、かつ空でないことをバリデートします。これはnullでない限り、他のフィールドはリクエストデータに存在しなければならないという意味でもあります。もしnullrequired_unless:name,null)の場合は、比較フィールドがnullであるか、リクエストデータに比較フィールドが存在しない限り、バリデーション対象下のフィールドは必須です。

required_with:foo,bar,...

指定した他のフィールドが一つでも存在している場合、このフィールドが存在し、かつ空でないことをバリデートします。

required_with_all:foo,bar,...

指定した他のフィールドがすべて存在している場合、このフィールドが存在し、かつ空でないことをバリデートします。

required_without:foo,bar,...

指定した他のフィールドのどれか一つでも存在していない場合、このフィールドが存在し、かつ空でないことをバリデートします。

required_without_all:foo,bar,...

指定した他のフィールドがすべて存在していない場合、このフィールドが存在し、かつ空でないことをバリデートします。

same:フィールド

フィールドが、指定されたフィールドと同じ値であることをバリデートします。

size:

フィールドは指定されたと同じサイズであることをバリデートします。文字列の場合、は文字長です。数値項目の場合、は整数値(属性にnumericintegerルールを持っている必要があります)です。配列の場合、は配列の個数(count)です。ファイルの場合、はキロバイトのサイズです。

// 文字列長が12文字ちょうどであることをバリデートする
'title' => 'size:12';

// 指定された整数が10であることをバリデートする
'seats' => 'integer|size:10';

// 配列にちょうど5要素あることをバリデートする
'tags' => 'array|size:5';

// アップロードしたファイルが512キロバイトぴったりであることをバリデートする
'image' => 'file|size:512';

starts_with:foo,bar,...

フィールドが、指定した値のどれかで始まることをバリデートします。

string

フィルードは文字列タイプであることをバリデートします。フィールドがnullであることも許す場合は、そのフィールドにnullableルールも指定してください。

timezone

timezone_identifiers_list PHP関数の値に基づき、フィールドがタイムゾーンとして識別されることをバリデートします。

unique:テーブル,カラム

フィールドが、指定されたデータベーステーブルに存在しないことをバリデートします。

カスタムテーブル/カラム名の指定

テーブル名を直接指定する代わりに、Eloquentモデルを指定することもできます。

'email' => 'unique:App\Models\User,email_address'

columnオプションは、フィールドの対応するデータベースカラムを指定するために使用します。columnオプションが指定されていない場合、バリデーション中のフィールドの名前が使用されます。

'email' => 'unique:users,email_address'

カスタムデータベース接続の指定

場合により、バリデータが行うデータベースクエリのカスタム接続を指定する必要があります。これには、接続名をテーブル名の前に追加します。

'email' => 'unique:connection.users,email_address'

指定されたIDのuniqueルールを無視する

場合により、uniqueのバリデーション中に特定のIDを無視したいことがあります。たとえば、ユーザーの名前、メールアドレス、および場所を含む「プロファイルの更新」画面について考えてみます。メールアドレスが一意であることを確認したいでしょう。しかし、ユーザーが名前フィールドのみを変更し、メールフィールドは変更しない場合、ユーザーは当該電子メールアドレスの所有者であるため、バリデーションエラーが投げられるのは望ましくありません。

バリデータにユーザーIDを無視するように指示するには、ルールをスラスラと定義できるRuleクラスを使います。以下の例の場合、さらにルールを|文字を区切りとして使用する代わりに、バリデーションルールを配列として指定しています。

use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

Validator::make($data, [
    'email' => [
        'required',
        Rule::unique('users')->ignore($user->id),
    ],
]);

{note} ユーザーがコントロールするリクエストの入力をignoreメソッドへ、決して渡してはいけません。代わりに、Eloquentモデルインスタンスの自動増分IDやUUIDのような、生成されたユニークなIDだけを渡してください。そうしなければ、アプリケーションがSQLインジェクション攻撃に対し、脆弱になります。

モデルキーの値をignoreメソッドに渡す代わりに、モデルインスタンス全体を渡すこともできます。Laravelはモデルからキーを自動的に抽出します:

Rule::unique('users')->ignore($user)

もし、テーブルの主キーとしてid以外のカラム名を使用している場合は、ignoreメソッドを呼び出す時に、カラムの名前を指定してください。

Rule::unique('users')->ignore($user->id, 'user_id')

uniqueルールはデフォルトで、バリデートしようとしている属性名と一致するカラムの同一性をチェックします。しかしながら、uniqueメソッドの第2引数として、異なったカラム名を渡すことも可能です。

Rule::unique('users', 'email_address')->ignore($user->id),

追加のWHERE節を付け加える

whereメソッドを使用してクエリをカスタマイズすることにより、追加のクエリ条件を指定できます。たとえば、account_id列の値が1の検索レコードのみ検索するクエリ条件で絞り込むクエリを追加してみます。

'email' => Rule::unique('users')->where(function ($query) {
    return $query->where('account_id', 1);
})

url

フィールドが有効なURLであることをバリデートします。

uuid

フィールドが有効な、RFC 4122(バージョン1、3、4、5)universally unique identifier (UUID)であることをバリデートします。

条件付きでルールを追加する

フィールドが特定値を持つ場合にバリデーションを飛ばす

他のフィールドに指定値が入力されている場合は、バリデーションを飛ばしたい状況がときどき起きるでしょう。exclude_ifバリデーションルールを使ってください。appointment_datedoctor_nameフィールドは、has_appointmentフィールドがfalse値の場合バリデートされません。

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ルールを使い、他のフィールドに指定値が入力されていない場合は、バリデーションを行わないことも可能です。

$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ルールをルールリストに追加します。

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

上の例ではemailフィールドが、$data配列の中に存在している場合のみバリデーションが実行されます。

{tip} フィールドが常に存在しているが、空であることをバリデートする場合は、この追加フィールドに対する注意事項を確認してください。

複雑な条件のバリデーション

ときどきもっと複雑な条件のロジックによりバリデーションルールを追加したい場合もあります。たとえば他のフィールドが100より大きい場合のみ、指定したフィールドが入力されているかをバリデートしたいときなどです。もしくは2つのフィールドのどちらか一方が存在する場合は、両方共に値を指定する必要がある場合です。こうしたルールを付け加えるのも面倒ではありません。最初にValidatorインスタンスを生成するのは、固定ルールの場合と同じです。

use Illuminate\Support\Facades\Validator;

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

私たちのWebアプリケーションがゲームコレクター向けであると仮定しましょう。ゲームコレクターがアプリケーションに登録し、100を超えるゲームを所有している場合は、なぜこれほど多くのゲームを所有しているのかを説明してもらいます。たとえば、ゲームの再販店を経営している場合や、ゲームの収集を楽しんでいる場合などです。この要件を条件付きで追加するには、Validatorインスタンスでsometimesメソッドを使用できます。

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

sometimesメソッドに渡される最初の引数は、条件付きでバリデーションするフィールドの名前です。2番目の引数は、追加するルールのリストです。3番目の引数として渡すクロージャがtrueを返す場合、ルールが追加されます。この方法で、複雑な条件付きバリデーションを簡単に作成できます。複数のフィールドに条件付きバリデーションを一度に追加することもできます。

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

{tip} クロージャに渡される$inputパラメーターは、Illuminate\Support\Fluentのインスタンスであり、バリデーション中の入力とファイルへアクセスするために使用できます。

複雑な条件の配列バリデーション

インデックスがわからない、入れ子になった同じ配列の中にある別のフィールドに基づいて、あるフィールドを検証したいことがあります。このような場合には、クロージャへ第2引数を渡してください。第2引数には、配列中のバリデーション対象の現アイテムが渡されます。

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

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

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

クロージャに渡される$inputパラメータと同様に、$itemパラメータは属性データが配列の場合はIlluminate\Support\Fluentのインスタンス、そうでない場合は文字列になります。

配列のバリデーション

arrayバリデーションルールのドキュメントで説明したように、arrayルールは、許可する配列キーのリストを受け入れます。配列内にその他のキーが存在する場合、バリデーションは失敗します。

use Illuminate\Support\Facades\Validator;

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

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

一般的には、配列内に存在を許す配列キーを常に指定する必要があります。そうしないと、バリデータのvalidatevalidatedメソッドは、配列とそのすべてのキーを含むバリデート済みデータをすべて返してしまいます。

バリデートできなかった配列キーの除外

必要に応じ、許可するキーのリストを指定せずにarrayルールを使用した場合でも、Laravelのバリデータが返す「検証済み」データに未検証の配列キーを含めないように指示できます。そうするには、アプリケーションのAppServiceProviderbootメソッドでバリデータのexcludeUnvalidatedArrayKeysメソッドを呼び出してください。それによりバリデータは、ネストする配列ルールにより検証された場合にのみ返される「検証済み」データへ配列キーを含めます。

use Illuminate\Support\Facades\Validator;

/**
 * 全アプリケーションサービスの登録
 *
 * @return void
 */
public function boot()
{
    Validator::excludeUnvalidatedArrayKeys();
}

ネストした配列入力のバリデーション

ネストした配列ベースフォームの入力フィールドをバリデーションするのが、面倒である必要はありません。配列内の属性をバリデーションするには、「ドット記法」が使えます。たとえば、HTTPリクエストにphotos[profile]フィールドが含まれている場合、次のように検証します。

use Illuminate\Support\Facades\Validator;

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

配列の各要素をバリデーションすることもできます。たとえば、特定の配列入力フィールドの各メールが一意であることをバリデーションするには、次のようにします。

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

同様に、言語ファイルのカスタムバリデーションメッセージを指定するときに*文字を使用すると、配列ベースのフィールドに単一のバリデーションメッセージを簡単に使用できます。

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

パスワードのバリデーション

パスワードが十分なレベルの複雑さがあることを確認するために、LaravelのPasswordルールオブジェクトを使用できます。

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

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

Passwordルールオブジェクトを使用すると、文字・数字・記号を最低1文字必要にしたり、文字種を組み合わせたりのように、パスワードの指定をアプリケーションで使用する複雑さの要件に合うよう簡単にカスタマイズできます。

// 最低8文字必要
Password::min(8)

// 最低1文字の文字が必要
Password::min(8)->letters()

// 最低大文字小文字が1文字ずつ必要
Password::min(8)->mixedCase()

// 最低一文字の数字が必要
Password::min(8)->numbers()

// 最低一文字の記号が必要
Password::min(8)->symbols()

さらに、uncompromisedメソッドを使って、公開されているパスワードのデータ漏洩によるパスワード漏洩がないことを確認することもできます。

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

内部的には、Passwordルールオブジェクトは、k-Anonymityモデルを使用して、ユーザーのプライバシーやセキュリティを犠牲にすることなく、パスワードがhaveibeenpwned.comサービスを介してリークされているかを判断します。

デフォルトでは、データリークに少なくとも1回パスワードが表示されている場合は、侵害されたと見なします。uncompromisedメソッドの最初の引数を使用してこのしきい値をカスタマイズできます。

// 同一のデータリークにおいて、パスワードの出現回数が3回以下であることを確認
Password::min(8)->uncompromised(3);

もちろん、上記の例ですべてのメソッドをチェーン化することができます。

Password::min(8)
    ->letters()
    ->mixedCase()
    ->numbers()
    ->symbols()
    ->uncompromised()

デフォルトパスワードルールの定義

パスワードのデフォルトバリデーションルールをアプリケーションの一箇所で指定できると便利でしょう。クロージャを引数に取るPassword::defaultsメソッドを使用すると、これを簡単に実現できます。defaultsメソッドへ渡すクロージャは、パスワードルールのデフォルト設定を返す必要があります。通常、defaultsルールはアプリケーションのサービスプロバイダの1つのbootメソッド内で呼び出すべきです。

use Illuminate\Validation\Rules\Password;

/**
 * アプリケーションの全サービスの初期処理
 *
 * @return void
 */
public function boot()
{
    Password::defaults(function () {
        $rule = Password::min(8);

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

そして、バリデーションで特定のパスワードへデフォルトルールを適用したい場合に、引数なしでdefaultsメソッドを呼び出します。

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

時には、デフォルトのパスワードバリデーションルールへ追加ルールを加えたい場合があります。このような場合には、rulesメソッドを使用します。

use App\Rules\ZxcvbnRule;

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

    // ...
});

カスタムバリデーションルール

ルールオブジェクトの使用

Laravelは有用な数多くのバリデーションルールを提供しています。ただし、独自のものを指定することもできます。カスタムバリデーションルールを登録する1つの方法は、ルールオブジェクトを使用することです。新しいルールオブジェクトを生成するには、make:ruleArtisanコマンドを使用できます。このコマンドを使用して、文字列が大文字であることを確認するルールを生成してみましょう。Laravelは新しいルールをapp/Rulesディレクトリに配置します。このディレクトリが存在しない場合、Artisanコマンドを実行してルールを作成すると、Laravelがそのディレクトリを作成します。

php artisan make:rule Uppercase

ルールを生成したら、動作を定義する準備ができました。ルールオブジェクトは2つのメソッドを含みます。passesmessageです。passesメソッドは属性の値と名前を受け取り、その属性値が有効であればtrue、無効であればfalseを返します。messageメソッドは、バリデーション失敗時に使用する、バリデーションエラーメッセージを返します。

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Uppercase implements Rule
{
    /**
     * バリデーションの成功を判定
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        return strtoupper($value) === $value;
    }

    /**
     * バリデーションエラーメッセージの取得
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute must be uppercase.';
    }
}

もちろん、翻訳ファイルのエラーメッセージを返したい場合は、messageメソッドからtransヘルパを呼び出せます。

/**
 * バリデーションエラーメッセージの取得
 *
 * @return string
 */
public function message()
{
    return trans('validation.uppercase');
}

ルールが定義できたら、他のバリデーションルールと一緒に、ルールオブジェクトのインスタンスをバリデータへ渡し、指定します。

use App\Rules\Uppercase;

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

追加データへのアクセス

カスタムバリデーションルールクラスがバリデーション下の他のすべてのデータへアクセスする必要がある場合、そのルールクラスにIlluminate\Contracts\Validation\DataAwareRuleインターフェイスを実装してください。このインターフェイスは、クラスへsetData メソッドの定義を要求します。このメソッドはLaravelにより自動的に(バリデーション処理前に)、バリデーション対象の全データで呼び出されます。

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\DataAwareRule;

class Uppercase implements Rule, DataAwareRule
{
    /**
     * バリデーション下の全データ
     *
     * @var array
     */
    protected $data = [];

    // ...

    /**
     * バリデーション下のデータをセット
     *
     * @param  array  $data
     * @return $this
     */
    public function setData($data)
    {
        $this->data = $data;

        return $this;
    }
}

または、バリデーションルールが、バリデーションを行うバリデータインスタンスへのアクセスを必要とする場合は、ValidatorAwareRuleインターフェイスを実装してください。

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidatorAwareRule;

class Uppercase implements Rule, ValidatorAwareRule
{
    /**
     * バリデータインスタンス
     *
     * @var \Illuminate\Validation\Validator
     */
    protected $validator;

    // ...

    /**
     * 現用バリデータのセット
     *
     * @param  \Illuminate\Validation\Validator  $validator
     * @return $this
     */
    public function setValidator($validator)
    {
        $this->validator = $validator;

        return $this;
    }
}

クロージャの使用

アプリケーション全体でカスタムルールの機能が1回だけ必要な場合は、ルールオブジェクトの代わりにクロージャを使用できます。クロージャは、属性の名前、属性の値、およびバリデーションが失敗した場合に呼び出す必要がある$failコールバックを受け取ります。

use Illuminate\Support\Facades\Validator;

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

暗黙のルール

デフォルトでは、バリデーションされる属性が存在しないか、空の文字列が含まれている場合、カスタムルールを含む通常のバリデーションルールは実行されません。たとえば、uniqueルールは空の文字列に対して実行されません。

use Illuminate\Support\Facades\Validator;

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

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

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

属性が空の場合でもカスタムルールを実行するには、ルールは属性が必須であることを意味する必要があります。「暗黙の」ルールを作成するには、Illuminate\Contracts\Validation\ImplicitRuleインターフェイスを実装します。このインターフェイスは、バリデータの「マーカーインターフェイス」として機能します。したがって、通常のRuleインターフェイスで必要なメソッド以外に実装する必要のある追加のメソッドは含まれていません。

新しい暗黙のルールオブジェクトを生成するには、make:rule Artisanコマンドに--implicitオプションを付けて使用してください。

 php artisan make:rule Uppercase --implicit

{note} 「暗黙の」ルールは、属性が必要であることを暗黙的にします。欠落している属性または空の属性を実際に無効にするかどうかは、あなた次第です。