Инструменты пользователя

Инструменты сайта


limb3:ru:packages:web_app:validation

Валидация данных

Limb3 жестко не навязывает Вам способ проверки данных, но предоставляет ряд средств, чтобы упростить этот процесс.

Мы решили поместить этот материал именно здесь, как так он затрагивает как минимум 4 пакета: ACTIVE_RECORD, VALIDATION, WACT и WEB_APP.

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

Словарь терминов

Словарь терминов, которые мы будем использовать на данной странице:

  • Контейнер с данными, который необходимо проверить (отвалидировать). Таким контейнером может быть Запрос (request), объект ActiveRecord, любой другой объект, который поддерживает интерфейс lmbDatasource (то есть содержит метод get($field_name)).
  • Ошибка валидации(validation error) - содержит сообщение об ошибке, список полей, к которым применяется сообщение(опционально), и список неверных значений (опционально), которые были введены в указанные поля.
  • Список ошибок (error_list) - содержит ошибки валидации, а также ссылку на словарь полей (см. ниже)
  • Правило валидации (validation_rule) - проверяет правильность одного или нескольких полей контейнера с данными.
  • Набор правил, или валидатор (validator) - содержит набор правил и ссылку на список ошибок. Применяет последовательно правила валидации к указанному контейнеру данных.
  • Словарь полей - применяется для получения полного имени поля контейнера данных, если список полей будет указан в ошибке валидации.

Общая схема валидации

Кратко процесс валидации данных можно описать следующим образом:

  1. Клиент (допустим это контроллер) создает пустой или какой-то конкретный валидатор, который содержит набор правил.
  2. Клиент также создает список ошибок (или же валидатор содержит список ошибок по-умолчанию) и передает его в валидатор
  3. Нужный контейнер данных передается в валидатор, который последовательно передает этот контейнер данных и список ошибок в каждое правило.
  4. Если правило валидации не срабатывает, то есть поле или несколько полей контейнера данных не удовлетворяют условию правила, оно добавляет ошибку в список ошибок, указывая текст ошибки, список ошибочных полей и неверные значения, если необходимо.
  5. Если после работы валидатора список ошибок не пуст - валидация считается неудавшейся
  6. Список ошибок далее может передаться контроллером в отображение (view) шаблон для отображения пользователю.
  7. При выводе список ошибок при помощи словаря полей преобразует каждое сообщение от ошибке в окончательный вид
  8. Шаблонизатор отображает конечные ошибки валидации

Это полная схема. На практике некоторые шаги могут быть пропушены. Например, вы можете отказаться от применение валидаторов с правилами и проверять данные, добавлять ошибки в список ошибок прямо в контроллере.

Валидатор. Класс lmbValidator. Создание своих валидаторов

Валидатор представлен в Limb3 классом lmbValidator.

Для добавления правил валидации lmbValidator содержит метод addRule($rule):

 lmb_require('limb/validation/src/lmbValidator.class.php');
 $validator = new lmbValidator();
 lmb_require('limb/validation/src/rule/lmbMatchRule.class.php');
 $validator->addRule(new lmbMatchRule('password', 'repeat_password'));

Правило обязательности поля lmbRequiredRule используется очень часто, поэтому для него есть специальный метод addRequiredRule($field_name):

 $validator->addRequiredRule('login');
 $validator->addRequiredRule('password');

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

lmb_require('limb/validation/src/lmbValidator.class.php');
 
class MyValidator extends lmbValidator
{
  function __construct()
  {
    $this->addRule(new lmbHandle('limb/validation/src/rule/lmbRequiredRule', array('name')));
    $this->addRule(new lmbHandle('limb/validation/src/rule/lmbSizeRangeRule', array('name', 5, 20)));
  }
}

Если же вы не используете отложенную инициализацию объектов (при помощи класса lmbHandle) или добавление правил связано с какими-либо условиями, которые проявляются только на этапе валидации, тогда добавление правил можно осуществлять в методе validate($datasource), который запускает процесс валидации контейнера данных:

lmb_require('lmbValidator.class.php');
 
class MyValidator extends lmbValidator
{
  function validate($datasource)
  {
    $this->addRule(new lmbHandle('limb/validation/src/rule/lmbRequiredRule', array('name')));
    $this->addRule(new lmbHandle('limb/validation/src/rule/lmbSizeRangeRule', array('name', 5, 20)));
 
    return parent :: validate($datasource);
  }
}

В качестве валидируемого контейнера данных ($datasource) в общем случае подойдет любой объект, который поддерживает метод get($field_name) (интерфейс lmbDatasource см. limb/datasource/src/lmbDatasource.interface.php).

Обычно новые валидаторы хранятся в папке /src/validation пакетов (приложения на базе Limb3 обычно также считаются пакетами), а новые правила валидации - в /src/validation/rule. Обратите внимание, что в пакете валидации правила валидации хранятся в папке /src/rule. Имейте это ввиду при использовании lmb_require или создании lmbHandle.

lmbValidator в качестве параметра конструктора может получать объект списка ошибок валидации. Таким образом можно в один список ошибок собрать ошибки от нескольких валидаторов. Если же список ошибок в конструктор валидатора не передан, то используется новый объект класса lmbErrorList.

Список ошибок можно также передать в валидатор при помощи метода setErrorList($error_list).

Список ошибок. Классы lmbErrorList

Пакет VALIDATION содержит реализацию списка ошибок в виде класса lmbErrorList.

Класс lmbErrorList отнаследован от класса lmbCollection, то есть это - полноценный итератор.

Класс lmbErrorList содержит следующие методы:

  • addError($message, $fields = array(), $values = array())
  • isValid() - возвращает true, если нет ошибок валидации, иначе false. Вместо isValid() можно примерять более базовый метод isEmpty(), что эквивалетно.

Если правило валидации обнаруживает ошибку в контейнере данных, тогда оно должно известить список ошибок посредством вызова метода addError($message, $field_list = array(), $values = array()). Поясним параметры этого метода:

  • $message - cообщение об ошибке. Обычно сообщение сразу же локализуется (переводится) при помощи глобальной функции tr().
  • $field_list - это или список пар «алиас ⇒ имя поля», которые имели ошибки или же просто список полей, содержащих ошибки, которые не подошли под какое-либо правило.
  • $values - список некоторых пар «алиас ⇒ значение», которые используются в сообщении об ошибке.

Например, вызов addError может выглядеть следующим образом:

$error_list->addError($message = tr('/validation', '{Field} must be greater than {min} characters.'),
                      $fields = array('Field' => 'name'),
                      $values = array('min' => 5));

При выводе ошибки валидации спец. места сообщения, например, {Field} и {min} будут заменены на соответствующие значения (см. ниже). При этом значение параметра $fields будут также обработаны при помощи словаря полей для получания человеко-понятных имен полей. В результате, в конечном итоге мы пожем получить следующее сообщение об ошибке: «Name must be greater than 5 characters».

Правило валидации. Интерфейс lmbValidationRule

lmbValidationRule - это интерфейс правила валидации пакета валидации данных. Интерфейс правила валидации состоит всего из одного метода: validate($dataspace, $error_list). То есть правило валидации получает просто контейнер с данными, которые нужно проверить и список ошибок, куда будут добавляться ошибки, в случае их наличия.

Часто используемые правила валидации

Правила валидации находятся в папке limb/validation/src/rule/

Имя классаНазначение
lmbSingleFieldRuleБазовый (абстрактный) класс для правил валидации, относящихся только к одному полю.
lmbRequiredRuleПроверяет, что поле обязательно присутствует в контейнере данных, который нужно проверить
lmbSizeRangeRuleПроверяет, что поле не больше определенной длины или находится в определенных рамках
lmbMatchRuleПроверяет, что два поля имеют одинаковые значения.
lmbPatternRuleПроверяет, что значение поле подходит под определенное регулярное выражение
lmbSimpleUrlRuleУдостоверяется, что значение поля является URL-адресом (достаточно примитивная проверка)
lmbDomainRuleУдостоверяется, что значение поля является именем домена
lmbInvalidValueRuleУдостоверяется, что поле имеет отличное от указанного в конструкторе правила значения
lmbUniqueTableFieldRuleПроверяет, что значение поля является уникальным для поля определенной таблицы в базе данных
lmbFileUploadRequiredRuleУдостоверяется, что файл был закачан
lmbFileUploadMaxSizeRuleУдостоверяется, что файл был закачан меньшего, чем указано размера
lmbFileUploadMimeTypeRuleУдостоверяется, что был закачан файл только определенного типа

Словарь полей. Класс WactFormFieldNameDictionary

Словарь полей преобразует имя поля в контейнере данных в полное название. Например login → «Your login». Cловарь полей должен поддерживать метод getFieldName($name).

Для большинства проектов, реализованных на Limb3, используется шаблонизатор WACT, который содержит класс WactFormFieldNameDictionary. WactFormFieldNameDictionary - использует информацию о том, как называются те или иные поля, исходя из того, что есть в шаблоне. Обычно используются значения атрибутов title, alt, или displayname полей ввода.

Необходимости создания своих словарей полей при использовании WACT-шаблонизатора обычно не возникает. Передача словаря полей в lmbErrorList происходит к классе lmbWactView пакета VIEW.

Если конкретный словарь для класса lmbErrorList не указан, тогда он использует в качестве полного названия поля его имя. То есть title → title.

Отображение ошибок валидации

Основная идея валидации состоит в том, чтобы наполнить единый список ошибок (конечно, если есть ошибки), проверяя данные различными средствами (валидатором или простым кодом) и передать этот список ошибок в шаблон.

Список ошибок валидации формы

Если вы используете WACT-шаблонизатор (в качестве View в WEB_APP по-умолчанию используется именно класс lmbWACTView) и пакет WEB_APP, тогда для передачи списка ошибок можно использовать метод lmbWactView :: setFormErrors($form_name, $error_list). Обычно это происходит автоматически, если вы вызываете метод lmbController :: useForm($form_name);

Если же вы работаете просто с шаблоном напрямую и используете класс lmbErrorList, тогда вам потребуется написать следующие строки:

$error_list = new lmbErrorList();
//... заполнение $error_list
$template = new WactTemplate('my_template.html');
$form = $template->findChild('my_form');
$error_list->setFieldNameDictionary(new WactFormFieldNameDictionary($form));
$form->setErrors($error_list->getReadable());

Обратите внимание на метод lmbErrorList :: getReadable(). В этом методе создается новый экземпляр класса lmbErrorList, однако сообщения об ошибках там уже полностью отформатированные, где все специальные места вида {Field}заменены на «человеко-понятные» значения, основанные на данных, полученных из полей формы.

Если же вы используете класс WactErrorList (например, при использовании WACT-а отдельно от других пакетов Limb3), который поддерживает схожий интерфейс, когда:

$error_list = new WactErrorList();
//... заполнение $error_list
$template = new WactTemplate('my_template.html');
$form = $template->findChild('my_form');
$error_list->bindToForm($form);

В этом случае, если у вас в шаблоне есть тег формы с атрибутом runat='server', список ошибок будет передан в активный компонент формы.

После этого мы сможете использовать следующие WACT-теги для отображения списка ошибок:

  • <form:errors> - передает список ошибок валидации в тег <list:list>, который найдет внутри себя (поведение начиная с версии WACT 0.3)
  • <form:field_errors> - передает список ошибок валидации для всех полей или только для конкретного поля в тег <list:list>, который найдет внутри себя (доступен начиная с версии WACT 0.3).

Пример:

<form name='my_form' runat='server' method='POST'>
 
<form:errors>
<list:list>
Form errors:
<ul>
 <list:item>
  <li><b>{$message}</b></li>
 </list:item>
</ul>
</list:list>
</form:errors>
 
</form>

Сообщение об ошибке - {$message}.

Список ошибок всех полей формы обычно шире, чем просто список ошибок, так как некоторые ошибки относятся к нескольким полям. Если вы выводите только общий список ошибок для всей формы - используйте тег <form:errors>, если же вы выводите ошибки рядом с полями ввода - тогда используйте тег <form:field_errors>.

Общий список ошибок

Локализация ошибок валидации

Сообщения об ошибках валидации переводятся сразу при помощи глобальной функции lmb_i18n(). Эта функция определена в пакете I18N, и таким образом обеспечивается перевод ошибок валидации.

Переводы сообщений находятся в файлах limb/validation/i18n/translations/validation.___.ts

Валидация данных в классе lmbController

Класс lmbController по-умолчанию содержит у себя 2 атрибута:

  • $validator - пустой валидатор, объект класса lmbValidator
  • $error_list - список ошибок, объект класса lmbErrorList

Для передачи ошибок валидации в форму обычно используется метод useForm($form_id), но можно написать и $this→view→setFormErrorList($this→error_list).

Небольшой пример:

<?php
lmb_require('src/model/User.class.php');
 
class LoginController extends lmbController
{
  function doDisplay()
  {
    if(!$this->request->hasPost())
      return;
 
    $this->useForm('login_form');
 
    $this->validator->addRequiredRule('login');
    $this->validator->addRequiredRule('password');
 
    $this->validator->validate($this->request);
 
    if($this->validator->isValid()) // можно было написать $this->error_list->isEmpty()
    {
      if(!$this->_loginAndPasswordCorrect())
       $this->error_list->addError('Сочетание логина и пароля неверное');
      else
       $this->_doReallyLoginUser();
    }
  }
  [...]
}
?>

Обсуждение

Ваш комментарий. Вики-синтаксис разрешён:
   __    ___    _  __   _  __   ____
  / /   / _ \  / |/ /  | |/_/  / __/
 / /__ / , _/ /    /  _>  <   _\ \  
/____//_/|_| /_/|_/  /_/|_|  /___/
 
limb3/ru/packages/web_app/validation.txt · Последние изменения: 2010/11/10 10:02 (внешнее изменение)