Передача пользовательских параметров в Laravel Validation с помощью регулярного выражения

Хорошо, у меня здесь очень сложная ситуация, и я думаю, что либо мне не хватает чего-то важного, что уже присутствует, либо Laravel не предоставляет способа достичь этого на данный момент. Я хотел бы указать настраиваемое сообщение об ошибке проверки с настраиваемым заполнителем, который я хотел бы заменить в сообщении. Проблема с этим: я использую правило проверки regex, о котором документация Laravel явно указывает, что его лучше передавать в массиве, чтобы избежать нежелательного поведения разделителя. Ситуация следующая: я хотел бы указать глобальное многоязычное сообщение для проверки name.regex, что я и сделал:

'custom' => [
    'name' => [
        'regex' => 'The :attribute must corespond to the given format: :format!'
    ]
]

Как видите, я поместил в это сообщение собственный заполнитель :format, потому что для атрибута name разных классов я собираюсь сопоставить разные регулярные выражения. Поэтому я хотел бы иметь возможность вводить настраиваемое удобочитаемое описание каждого заданного регулярного выражения во время проверки (в качестве параметра). Итак, я делаю в своем контроллере следующее:

$input = Input::all();
$validator = Validator::make($input, [
        'name' => ['required', 'regex:/^\p{Lu}\p{L}+ \p{Lu}\p{L}+$/u']
    ]);

У меня также есть Validator::replacer() метод в моем AppServiceProvider.php, который должен заменить заполнитель :format в сообщении:

Validator::replacer('regex', function($message, $attr, $rule, $parameters){
        return str_replace(':format', "I would like to be able to somehow retrieve the custom format description here, but using \$parameters[] is not an option", $message);
    });

Проблема с правилом проверки regex заключается в том, что мне действительно не разрешено передавать ему параметр в валидаторе, например, так:

$validator = Validator::make($input, [
        'name' => ['required', 'regex:/^\p{Lu}\p{L}+ \p{Lu}\p{L}+$/u,Thats my custom validator format description']
    ]);

потому что это полностью портит регулярное выражение (что и должно быть). Поэтому я не могу использовать $ parameters 1 $ в моем replacer() для замены заполнитель. Кроме того, было бы действительно неудобно передавать целое предложение в качестве параметра правила проверки, разделенного запятыми. Так что эта концепция не соответствует потребностям.

Значение :format будет динамическим и будет сильно различаться в зависимости от требований name полей разных классов, поэтому мне действительно нужно, чтобы это динамическое многоязычное описание было установлено как свойство текущего экземпляра валидатора. Я подумал, что, может быть, наиболее удобным сценарием будет что-то вроде этого:

$validator = Validator::make($input, [
        'name' => ['required', 'regex:/^\p{Lu}\p{L}+ \p{Lu}\p{L}+$/u', 'format:Current name requirements described here.']
    ]);

и Laravel каким-то образом знает, что :format следует заменить текущим правилом где-нибудь в сообщениях этого экземпляра. Я думал о том, чтобы явно добавить этот дополнительный параметр в качестве правила проверки, а затем управлять им, но я действительно не могу добиться соединения между правилами (другими словами, получить параметр нового правила format и использовать его в regex правило). Я действительно не знаю, как подойти к этой проблеме, и любая помощь будет принята с благодарностью. Заранее спасибо!

P.S. Я знаю, что могу каждый раз указывать все сообщение следующим образом:

$input = Input::all();
$validator = Validator::make($input, [
        'name' => ['required', 'regex:/^\p{Lu}\p{L}+ \p{Lu}\p{L}+$/u']
    ],
[
    'name.regex' => 'My custom message here'
]);

но я не хочу вводить все сообщение каждый раз, потому что позже оно может содержать другие заполнители (которые могут быть глобальными или около того), и я хочу использовать многоязычное базовое сообщение, предоставленное через файлы validator.php, поэтому Мне действительно нужно заменить только :format.


person D. Petrov    schedule 25.05.2018    source источник


Ответы (2)


Вы можете создать собственное правило:

php artisan make:rule CustomRegex

Затем обновите конструктор, чтобы он поддерживал как регулярное выражение, так и описание формата.

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class CustomRegex implements Rule
{
    /** @var string $attribute The attribute of we are validating. */
    public $attribute;

    /** @var string $description The description of the regex format. */
    public $description;

    /** @var string $regex The regex to validate. */
    public $regex;

    /**
     * Create a new rule instance.
     *
     * @param string $regex The regex to validate.
     * @param string $description The description of the regex format.
     * @return void
     */
    public function __construct(string $regex, string $description)
    {
        $this->regex = $regex;
        $this->description = $description;
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        $this->attribute = $attribute;

        return preg_match($this->regex, $value);
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return trans('validation.custom.name', [
            'attribute' => $this->attribute,
            'format' => $this->description
        ]);
    }
}

А затем, когда вы подтвердите:

use App\Rules\CustomRegex;

request()->validate([
    'name' => [
        'required', new CustomRegex('/^\p{Lu}\p{L}+ \p{Lu}\p{L}+$/u', 'The description of your format')
    ]
]);

Тогда выходное сообщение будет выглядеть так:

Имя должно соответствовать заданному формату: Описание вашего формата!

person Chin Leung    schedule 25.05.2018
comment
Подумал об этом на мгновение после того, как проснулся сегодня, теперь я вижу, что вы упомянули то же самое! Спасибо! Буду рад, если это будет добавлено в следующих версиях. Я имею в виду, просто немного более подробная версия правила regex, чтобы вы также могли передавать параметры. В этом нет особой необходимости, но было бы полезно. - person D. Petrov; 26.05.2018

Самый простой способ, как я понял в Laravel 5.6, - использовать закрытие:

$validator = Validator::make($input, 
    [
        'name' => 
           [
             'required',
             function($attribute, $value, $fail) {

                 $regex = '/^\p{Lu}\p{L}+ \p{Lu}\p{L}+$/u';

                 if (!preg_match($regex, $value)) {

                    return $fail('Your custom message with' .
                    $attribute . ' name and its value = ' . $value);
                 }
             },
           ]
    ]);

Внутри этой крышки вы можете добавить все, что захотите. Вы можете рассчитать форму в удобном для чтения формате и добавить ее в сообщение об ошибке.

person Petya    schedule 25.05.2018
comment
Посмотрите мой последний постскриптум. Этот вид функциональности (установка текущего сообщения об ошибке [b] целое [/ b]) уже доступен через третий аргумент функции Validator::make() ($messages). Проблема в том, что я действительно не хочу каждый раз переписывать все сообщения, а просто чтобы иметь возможность вводить этот единственный параметр моих собственных [b] и [/ b], по-прежнему использую базу сообщений, указанную в validator.php переводе файл. - person D. Petrov; 25.05.2018