Статьи

Проверка данных в Laravel: правильный путь — пользовательские валидаторы

В предыдущей части мы узнали, как проверять данные в Laravel, используя встроенный пакет проверки данных, и как абстрагировать нашу проверку данных для сервисов, специфичных для сущностей, чтобы сделать код повторно используемым на принципах DRY. Теперь мы можем легко создать службу проверки для каждой сущности в нашем приложении с собственными соответствующими правилами проверки, внедрять ее везде, где мы хотим проверять данные, и легко извлекать и отображать ошибки и т. Д.

Но что, если мы хотим больше?

Исходный код этого урока доступен здесь . Вам нужно просто запустить composer install чтобы установить среду Laravel внутри директории проекта, прежде чем вы сможете запустить этот код.

Потребность в большем

Из коробки Laravel предоставляет много полезных и общих правил проверки. Но что, если мы хотим больше? Что если нам нужно что-то более конкретное? В нашем примере здесь, в TestFormValidator мы использовали alpha_dash для проверки имен, но это не идеально для проверки полного имени. Обычно полное имя человека состоит из имени, фамилии и, возможно, отчества. Все это будет разделено пробелом. Точно так же, если мы хотим проверить пин-код в нашей форме, мы не можем использовать правило alpha_num предоставленное Laravel, мы также должны иметь возможность использовать пробелы в нем.

Что ж, Laravel предоставляет возможность легко расширить свой пакет проверки и добавить в него собственные правила проверки. В RocketCandy/Services/Validation/ создайте ValidatorExtended.php и добавьте в него следующий код:

 <?php namespace RocketCandy\Services\Validation; use Illuminate\Validation\Validator as IlluminateValidator; class ValidatorExtended extends IlluminateValidator { private $_custom_messages = array( "alpha_dash_spaces" => "The :attribute may only contain letters, spaces, and dashes.", "alpha_num_spaces" => "The :attribute may only contain letters, numbers, and spaces.", ); public function __construct( $translator, $data, $rules, $messages = array(), $customAttributes = array() ) { parent::__construct( $translator, $data, $rules, $messages, $customAttributes ); $this->_set_custom_stuff(); } /** * Setup any customizations etc * * @return void */ protected function _set_custom_stuff() { //setup our custom error messages $this->setCustomMessages( $this->_custom_messages ); } /** * Allow only alphabets, spaces and dashes (hyphens and underscores) * * @param string $attribute * @param mixed $value * @return bool */ protected function validateAlphaDashSpaces( $attribute, $value ) { return (bool) preg_match( "/^[A-Za-z\s-_]+$/", $value ); } /** * Allow only alphabets, numbers, and spaces * * @param string $attribute * @param mixed $value * @return bool */ protected function validateAlphaNumSpaces( $attribute, $value ) { return (bool) preg_match( "/^[A-Za-z0-9\s]+$/", $value ); } } //end of class //EOF 

Здесь наш класс расширяет класс Laravel Illuminate\Validation\Validator и добавляет два новых метода ( validateAlphaDashSpaces() и validateAlphaNumSpaces() ) для проверки данных и соответствующих им сообщений об ошибках с :attribute placeholder :attribute в них, который Laravel будет заменять во время выполнения с именем какое бы поле данных не проверялось.

Теперь следует отметить, как мы называем методы. Все имена методов правил валидации должны иметь префикс validate а остальная его часть должна быть в Заглавном регистре (без пробелов, конечно). Правило валидации будет в нижнем регистре с именем метода (без префикса validation ), и каждое слово будет разделено подчеркиванием. Поэтому, если мы хотим добавить alpha_dash_spaces проверки alpha_dash_spaces тогда наш соответствующий метод будет называться validateAlphaDashSpaces() .

Итак, мы добавили здесь правила проверки alpha_dash_spaces и alpha_num_spaces . alpha_dash_spaces будет разрешать буквы, тире (дефисы и подчеркивания) и пробелы, в то время как alpha_num_spaces будет разрешать только буквы, цифры (цифры 0-9) и пробелы.

Мы еще не закончили с этим, этот класс только расширяет класс проверки Laravel. Нам все еще нужно, чтобы Laravel распознал это, чтобы, когда мы добавим новые правила в наш сервис проверки, Laravel знал, как выполнить проверку согласно этим правилам.

Документы Laravel утверждают, что мы можем сделать это:

 Validator::resolver( function( $translator, $data, $rules, $messages ) { return new \RocketCandy\Services\Validation\ValidatorExtended( $translator, $data, $rules, $messages ); } ); 

и app/start/global.php его в app/start/global.php или, возможно, создайте новый файл в каталоге app и загрузите этот файл в app/start/global.php . Но это не выглядит так чисто, модифицируя файлы, которые нам не нужно модифицировать, вставляя кусочки в разные стороны. Нет, мы бы лучше держали весь этот код, связанный с проверкой, вместе, поэтому мы собираемся создать поставщика услуг и склеить наши пользовательские правила проверки в пакет проверки Laravel.

Создайте ValidationExtensionServiceProvider.php внутри RocketCandy/Services/Validation/ и добавьте в него следующий код:

 <?php namespace RocketCandy\Services\Validation; use Illuminate\Support\ServiceProvider; class ValidationExtensionServiceProvider extends ServiceProvider { public function register() {} public function boot() { $this->app->validator->resolver( function( $translator, $data, $rules, $messages = array(), $customAttributes = array() ) { return new ValidatorExtended( $translator, $data, $rules, $messages, $customAttributes ); } ); } } //end of class //EOF 

Если вы создали сервис-провайдера в Laravel раньше, вы обычно использовали бы метод register() для выполнения любой необходимой вам привязки. Это единственный abstract метод в абстрактном классе Illuminate\Support\ServiceProvider который мы расширили здесь. Причина, по которой мы не можем склеить наше расширение проверки в register() заключается в том, что оно запускается, как только Laravel загружает поставщика услуг, и мы сталкиваемся с множеством исключений, которые нам выдаются, поскольку Laravel инициализирует его пакет проверки позже, поэтому пытаться расширить вещи, которых нет, используя объект, который не существует. Метод boot() с другой стороны, запускается непосредственно перед перенаправлением запроса, поэтому мы можем безопасно приклеить наш материал к пакету проверки Laravel.

Теперь нам просто нужно сказать Laravel, чтобы загрузить этого поставщика услуг, и мы были бы готовы. Откройте ваш app/config/app.php и в массиве providers добавьте следующее в конце:

 'RocketCandy\Services\Validation\ValidationExtensionServiceProvider', 

Теперь откройте app/RocketCandy/Services/Validation/TestFormValidator.php и обновите свойство $rules так, чтобы оно выглядело так:

 public $rules = array( 'name' => array( 'required', 'alpha_dash_spaces', 'max:200' ), 'email' => array( 'required', 'email', 'min:6', 'max:200' ), 'phone' => array( 'required', 'numeric', 'digits_between:8,25' ), 'pin_code' => array( 'required', 'alpha_num_spaces', 'max:25' ), ); 

Мы заменили alpha_dash проверки alpha_dash для name на alpha_dash_spaces и alpha_num для pin_code на alpha_num_spaces .

Теперь, если мы перейдем по http://<your-project-domain>/dummy/create мы можем без проблем ввести пробелы в поля «Имя» и «Пин-код», и данные пройдут проверку при отправке.

Резюме

Итак, в этом уроке из двух частей мы научились:

  1. Проверяйте данные в Laravel, используя встроенный пакет проверки данных.
  2. Используйте объектно-ориентированный подход, чтобы абстрагировать валидацию данных в отдельный сервис (разблокированное достижение « Одна ответственность» ).
  3. Создайте наши собственные пользовательские исключения для использования с нашей службой проверки данных (вместо использования логических значений TRUE/FALSE ) и способы хранения и получения ошибок из них.
  4. Добавьте наш сервис проверки данных в наш Контроллер и используйте его.
  5. Расширьте пакет проверки Laravel с помощью наших пользовательских правил проверки и автоматически загрузите его с помощью поставщика услуг.

Сноски

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


Есть мысли? Вопросов? Огонь в комментариях.