開発ブログ

株式会社Nextatのスタッフがお送りする技術コラムメインのブログ。

電話でのお問合わせ 075-744-6842 ([月]-[金] 10:00〜17:00)

  1. top >
  2. 開発ブログ >
  3. PHP >
  4. Laravel >
  5. カスタムバリデーションについてのメモ
no-image

カスタムバリデーションについてのメモ

こんにちは、最近花粉症のせいで毎日が辛いヤマモトです。
先日仕事でバリデーションを修正する必要があり、森さんが書いていただいた記事を確認したりしました。
その中でも独自のカスタムバリデーションルールの作成に関して自分が勉強になった部分を、参考になればと思いご紹介いたします。
 

環境

  • PHP: 8.1.8
  • Laravel Framework: 9.22.1

Laravel9で変更になった箇所

Laravelにはデフォルトで様々なバリデーションルールが使用可能で、こちらの記事にもあるようにmissingが追加されるなど日々改善されています。
しかし、それでは足りない場合に独自のものを指定することもできます

 そこでカスタムバリデーションルールを追加してあげることで指定可能となります。
Laravel9では少し変更があったので注意が必要です。

カスタムバリデーションルールを登録するためにルールオブジェクトを作成していきます。
以下のmake:ruleコマンドを実行します。
 
php artisan make:rule customUppercase --invokable

ルールを作成したら動作自体を定義する必要があります。

ここまでは以前Laravel8以前のバージョンでも行えましたがルールオブジェクトは2つのメソッドを含みます。passesとmessageを定義してカスタムルールを作成していました。
以下のように定義できます。
 
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.';
    }
}

Laravel9では、コマンドで生成したルールオブジェクトには__invokeという1つのメソッドが用意されています。
以下のようにすっきりとした定義ができるようになっています。
class Uppercase implements InvokableRule
{
    /**
   * Run the validation rule.
   *
   * @param  string  $attribute
   * @param  mixed  $value
   * @param  \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString  $fail
   * @return void
   */
   public function __invoke($attribute, $value, $fail)
  {
     if (strtoupper($value) !== $value) {
        $fail('The :attribute must be Uppercase');
    }
  }
}


このメソッドで属性名とその値、バリデーションエラーメッセージと失敗時に呼び出すコールバックを指定することができるようになっています。
 
/**
* Get the validation rules that apply to the request.
*
* @return array
*/   
public function rules()
{
    return [
        'Name' => ['required', 'string', new CustomeUppercase],
    ];
}


文字列へのメッセージを指定する代わりに翻訳文字列キーを指定することでLaravelの
エラーメッセージ翻訳も使用することができます。
 

エラーメッセージの翻訳に関する変更


翻訳ファイルのエラーメッセージを返したい場合にも少し違いがあるのでご紹介します。
Laravel8以前ではmessageメソッドからtransヘルパを使用してあげることで翻訳ファイルの定義を利用することが可能です。
/**
 * バリデーションエラーメッセージの取得
 *
 * @return string
 */
public function message()
{
    return trans('validation.uppercase');
}

Laravel9では、ルールオブジェクトの__invoke()の第三引数の $fail というコールバックに渡した文字列が自動的に翻訳に通されてエラーメッセージとなります。
 
    public function __invoke($attribute, $value, $fail)
    {
        if (strtoupper($value) !== $value) {
            $fail('validation.uppercase')->translate();
        }
    }

一度だけカスタムルールの機能を使用したい時は
クロージャを使用してあげることも可能です。
    public function rules()
    {
        return [
            'Name' => [
        'required',
                'string',
                function ($attribute, $value, $fail) {
                    if ($value == "aho") {
                        $fail('The' . $attribute . 'is not good name.');
                    }
                }
         ],
        ];
    }
 

ちょいメモ(暗黙のルールについて)

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

 
use Illuminate\Support\Facades\Validator;

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

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

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

属性が空の場合でもカスタムルールを実行するには、ルールがその属性を必要とすることを示す必要があります。簡単に新しい暗黙のルールオブジェクトを生成するには、make:rule Artisanコマンドに、--implicitオプションを付けて使用します。
 
php artisan make:rule Uppercase --invokable --implicit


該当ファイル内には下記のような記載が追加されていました。
こちらで空の属性を無効にすることができます
 
    /**
     * Indicates whether the rule should be implicit.
     *
     * @var bool
     */
    public $implicit = true;

最後に

今回は、カスタムバリデーションルールに関して自分なりに勉強になった部分をまとめてみました。
Laravel9でメソッドの数などに変更があったので少しでも参考になれば幸いです。

参考リンク
https://readouble.com/laravel/9.x/ja/validation.html
https://laravel.com/docs/9.x/validation#implicit-rules
 
  • posted by やまちゃん
TOPに戻る