こんばんは。もふもふおじさんです。
暗黙のルール
デフォルトでは、バリデーションされる属性が存在しないか、空の文字列が含まれている場合、カスタムルールを含む通常のバリデーションルールは実行されません。たとえば、uniqueルールは空の文字列に対して実行されません。
カスタムバリデーションでrequired_ifに似たような機能を作成した際、上記仕様がネックとなったので対応策を記載します。
今回は、カスタムバリデーションルール「required_if_regex」を作成することとします。
機能としてはrequired_ifを正規表現に対応させた感じです。(使用例: 'required_if_regex:name,^laravel')
まずは、サービスプロバイダーを作成し、設定ファイルに追加します。
app/Providers/ValidatorServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ValidatorServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
\Validator::resolver(function ($translator, $data, $rules, $messages) {
return new \App\Validator\CustomValidator($translator, $data, $rules, $messages);
});
}
}
config/app.php
'providers' => [
App\Providers\ValidatorServiceProvider::class,
..
次に本題のカスタムバリデーターを作成します。
やることは、カスタムバリデーターの継承元となるIlluminate\Validation\Validator.phpに定義された配列「$implicitRules」へ'RequiredIfRegex'ルールの追加です。
vendor/laravel/framework/src/Illuminate/Validation/Validator.php
/**
* The validation rules that imply the field is required.
*
* @var string[]
*/
protected $implicitRules = [
'Accepted',
'AcceptedIf',
'Declined',
'DeclinedIf',
'Filled',
'Missing',
'MissingIf',
'MissingUnless',
'MissingWith',
'MissingWithAll',
'Present',
'Required',
'RequiredIf',
'RequiredIfAccepted',
'RequiredUnless',
'RequiredWith',
'RequiredWithAll',
'RequiredWithout',
'RequiredWithoutAll',
];
app/Validator/CustomValidator.php
<?php
namespace App\Validator;
use Illuminate\Validation\Validator
class CustomValidator extends Validator {
public function __construct(Translator $translator, array $data, array $rules,
array $messages = [], array $customAttributes = [])
{
parent::__construct($translator, $data, $rules, $messages, $customAttributes);
$this->$implicitRules[] = Str::studly('required_if_regex');
}
public function validateRequiredIfRegex($attribute, $value, $parameters)
{
$other_value = Arr::get($this->data, $parameters[0]);
$pattern = $parameters[1] ?? null;
if ($pattern && preg_match('/' . $pattern . '/', $other_value)) {
return $this->validateRequired($attribute, $value);
}
return true;
}
}