Laravel10からInvokable検証ルールがデフォルトに

## はじめに
Laravel9で導入された[Invokable 検証ルール](https://github.com/laravel/framework/pull/42689 "Invokable 検証ルール")がLaravel10からデフォルトとなったため、そちらの紹介をします。
※Laravelの独自バリデーションの手法の1つになります。

上記リンク先にも記載の通り、Laravel9時点で導入されその時点ではオプション指定しないと作成できない状態でしたが、Laravel10になってからは推奨となりオプションなしで作成することができるようになりました。

## 利用シーン
Laravel標準で用意されているバリデーションでは対応できない場合に、独自のバリデーションとして定義することが多いです。

## 実行環境
Laravel Framework 10.23.1

## ルールファイルの作成
まずはルールファイルを作成します。
以下、ルールファイルを作成するためのコマンドです。

```command
php artisan make:rule MbDigit
```

自動的に以下のファイルが作成される。
```php:MbDigit.php
<?php

namespace App\Rules;

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

class MbDigit implements ValidationRule
{
    /**
     * Run the validation rule.
     *
     * @param  \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString  $fail
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        //
    }
}

```
:::note info
余談だが、Laravel9で通常ルールで作成すると以下のようなファイルになリます。
(処理も記述してあるサンプルファイル)
メソッドが分かれていない分、Invokable検証ルールの方がよりシンプルになっており、validateメソッドの引数$failは失敗時に実行されるコールバック関数なので、messageとして返却する必要がなくなりました。

```php:Quantity.php
class Quantity implements Rule
{
    protected $messages = [];

    public function passes($attribute, $value)
    {
        if (! is_array($value)) {
            $this->messages[] = trans('validation.quantity.must_be_an_object');

            return false;
        }

        if (! array_key_exists('magnitude', $value)) {
            $this->messages[] = trans('validation.quantity.missing_magnitude');
        }

        if (! array_key_exists('units', $value)) {
            $this->messages[] = trans('validation.quantity.missing_units');
        }

        return $this->messages === [];
    }

    public function message()
    {
        return $this->messages;
    }
}
```
:::

## ルールファイルにチェックしたい内容を記述
一例としてチェック処理を記述。
コンストラクタで呼び出し元からの値も設定可能です。

```php:MbDigit.php
<?php

namespace App\Rules;

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

class MbDigit implements ValidationRule
{
    private readonly int $digit;
    private readonly string $item_name;

    public function __construct(int $digit, string $item_name)
    {
        $this->digit = $digit;
        $this->item_name = $item_name;
    }

    /**
     * Run the validation rule.
     *
     * @param \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString $fail
     */
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (!mb_ereg("^.{{$this->digit}}$", $value)) {
            $fail("{$this->item_name}は{$this->digit}文字でなければいけません");
        }
    }
}


```

## ルールファイルをリクエストクラスから呼ぶ
ビューおよびコントローラーは割愛します。
ルールに違反した際に、画面には「記号は3文字でなければいけません」と表示されます。


```php:TestRequest.php
<?php

namespace App\Http\Requests\test;

use App\Rules\MbDigit;
use Illuminate\Foundation\Http\FormRequest;

class TestRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules(): array
    {
        return [
            'symbol' => [
                'required', new MbDigit(3, '記号')
            ]
        ];
    }
}

```

## まとめ
個人的に良いと感じた点は以下になります。
- コードがシンプルになったことで、利用する際の学習コストが減少する。
- コード量が減るため可読性が向上する。