5.5より前のバージョンのLaravelでプログラムをしていたひとたちに取っては、5.5で登場したルールオブジェクトは神の恵みと言ってもいいくらい。カスタムバリデーションを作成するために、Validator::extendはどこに宣言するの?とか、グローバルでどう作成したバリデーションを共有するの?とか、取り掛かる前に悩んでいたのがウソのよう。新登場のルールオブジェクトのおかげで、カスタムルールの作成が楽しくなりました。
カスタムルールが必要となるときは、たくさんあります。なぜなら既存のバリデーションでは簡単にいかないルールが世の中にたくさんあるからです。
例えば、登録したユーザーのリストが欲しいとして、開始日を指定して今日までに登録したユーザーのみとします。しかし、開始日は今日から2か月までしか遡れない、とします。以下のようなカレンダーで開始日をしてもらいますが、開始日が2か月以上前ならバリデーションでチェックしてエラーを表示としたいです。

このバリデーションには既存のバリデーションのafter_or_equalが使えます、しかし渡すパラメータには、「今日マイナス2か月」が必要です。もちろん前もって計算して渡すこともできます。
Psy Shell v0.9.9 (PHP 7.2.16 — cli) by Justin Hileman
>>> $from = \Carbon\Carbon::today()->subMonth(2)->toDateString();
=> "2019-01-29"
>>> $input = ['start_date' => '2019-01-01'];
=> [
"start_date" => "2019-01-01",
]
>>> validator($input, ['start_date' => 'required|date|after_or_equal:$from'])->errors()->all();
=> []
>>> validator($input, ['start_date' => "required|date|after_or_equal:$from"])->errors()->all();
=> [
"start dateは2019-01-29以後の日付が必要です",
]
>>>
しかし、もしかしたら2か月でなく3ヶ月となるかもしれないし、一般的なバリデーションがあってもいいですね。こんな感じで呼び出したいです。
['start_date' => ['required', 'date', new RestrictPeriodRule(2)]];
そこで、ルールオブジェクトの出番です。
まず、コマンドでルールのファイルを作成します。
$ php artisan make:rule RestrictPeriodRule
中身を以下のように編集します。
<?php
namespace App\Rules;
use Carbon\Carbon;
use Illuminate\Contracts\Validation\Rule;
class RestrictPeriodRule implements Rule
{
protected $months;
protected $start;
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct($months)
{
$this->months = $months;
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
$this->start = Carbon::today()
->subMonth($this->months)
->toDateString();
return ($value >= $this->start);
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return $this->start.'以降を指定してください';
}
}
出来たところでテストしてみましょう。
Psy Shell v0.9.9 (PHP 7.2.16 — cli) by Justin Hileman
>>> $input = ['start_date' => '2019-01-01'];
=> [
"start_date" => "2019-01-01",
]
>>> validator($input, ['start_date' => ['required', 'date', new App\Rules\RestrictPeriodRule(2)]])->errors()->all();
=> [
"2019-01-29以降を指定してください",
]
>>>
メルマガ購読の申し込みはこちらから。
