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以降を指定してください", ] >>>メルマガ購読の申し込みはこちらから。