Контент


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

Тема данной статьи — валидация, т.е. проверка входных данных на соответствие каким-то заранее определенным правилам. Самый простой пример — проверка URL или адреса Email на корректность, т.е. на наличие домена, «собачки» и т.д. В общем, вешь полезная во всех отношениях. Поэтому мы с ней в этой статье попробуем подружиться. За валидацию отвечает библиотека Validation (system/libraries/Validation.php).

Методы объекта Validation

  • Конструктор. В качестве параметра передается массив переменных (обычно это глобальный массив $_POST или $_GET), которые надо проверить. Вызывать можно различным образом, самое простое:

    $valid = new Validation($_POST);
     
    // или
     
    $valid = Validation::factory($_POST);

    Обратите внимание, что массив не копируется, а передается по ссылке, т.е. доступен для изменений (вообще он преобразовывается в объект ArrayObject).

  • Метод add_rules(). Для того, чтобы проверять переменные, надо указать правила. Первый параметр всегда имя переменной (т.е. ключ в переданном массиве). Кроме того, можно передать в качестве имени поля звездочку (символ ‘*’) или TRUE, тогда правило будет применено ко всем проверяемым полям. Далее следуют правила, которые могут быть встроенными (это наиболее распространенные правила, такие как required и email), так и определенными пользователем (в этом случае необходимо указать объект и имя метода этого объекта) — такие правила называют callback (или custom callback). Примеры использования:

    // Поле 'email' должно присутствовать и соответствовать стандартному правилу email
     
    $valid->add_rules('email', 'required', 'email');
     
    // Поле 'username' должно присутствовать и длина от 5 до 30 символов
     
    $valid->add_rules('username', 'required', 'length[5,30]');
     
    // Поле 'username' должно присутствовать и быть уникальным
     
    // Метод unique_username должен быть определен в текущем классе (т.к. передали $this)
     
    $valid->add_rules('username', 'required', array($this, 'unique_username'));

    Правила можно задать отдельно:

    $valid->add_rules('email', 'required');
     
    $valid->add_rules('email', 'email');

  • Метод add_callbacks(). По сути дублирует метод add_rules в части добавления собственных правил (callback‘ов). Параметры те же — имя поля и массив( объект, имя метода). Например:

    // свое правило для проверки пароля
     
    $valid->add_callbacks('password', array($this, 'check_password'));

  • Метод add_error(). Добавляет ошибку валидации в список ошибок. Первый параметр — имя поля, второй — текст ошибки (даже скорее что-то вроде метки). Стандартные правила сами составляют список ошибок, этот метод обычно используется в теле callback‘а.
  • Методы pre_filter() и post_filter(). Позволяют выполнять строковые преобразования над значениями полей до или после проверки. В качестве первого параметра выступает имя функции, второй — имя поля (если не указано, то распространяется на все поля). Пример:

    $valid->pre_filter('trim');
     
    // указываем правила
     
    $valid->post_filter('ucfirst', 'username');

    Функции trim() и ucfirst() являются встроенными php-функциями.

  • Метод validate(). Тут-то и происходит собственно валидация. Метод возвращает TRUE (ошибок нет) или FALSE (что-то не совпало).

Стандартные правила

Поскольку в 90% случаев используются стандартные правила, посмотрим, что мы имеем:

  • required. Поле должно существовать. Дополнительных параметров нет.
  • matches. Поле должно совпадать с указанным или указанными полями. Необходимо указать массив полей для сравнения.
  • length. Проверка на длину поля. Если передан один параметр, то проверяется равенство длины поля этому параметру. Если два, то первый принимается за минимальную длину, второй за максимальную. Пример:

    $valid->add_rules('password', 'length[5,10]'); // пароль от 5 до 10 символов
     
    $valid->add_rules('username', 'length[7]'); // все логины должны быть длиной 7 символов

  • depends_on. Ставим поле в зависимость от внесения другого поля или полей. Если хотя бы одно поле отсутствует или равно NULL, правило возвращает FALSE. Пример:

    // Поле total_price зависит от наличия полей price и count
     
    $valid->add_rules('total_price', 'depends_on[price, count]');

  • chars. Указывается перечень допустимых символов, из которых должно состоять значение проверяемого поля. Пример:

    // Поле должно быть в восьмеричной системе счисления
     
    $valid->add_rules('oct_value', 'chars[0,1,2,3,4,5,6,7]');

Эти правила описаны в самом классе Validation. Также можно использовать правила из хэлпера valid:

  • email. Проверка на корректность составления адреса email.
  • email_domain. Проверка домена email на существование в DNS записях по типу «MX» (выполняется функцией checkdnsrr()). Т.к. на windows-платформах такой функции нет, вернет TRUE.
  • email_rfc. Проверка email на корректность в соответствии с документом rfc822.
  • url. Проверяет url на валидность.
  • ip. Проверяет ip-адрес, в качестве дополнительных параметров можно указать поддержку адресов IPv6 и приватных сетей (диапазоны 10.0.0.0 — 10.255.255.255, 172.16.0.0 — 172.31.255.255, 192.168.0.0 — 192.168.255.255), указав TRUE в качестве соответствующего параметра.
  • credit_card. Проверка номеров кредитных карт на состав, длину, также используется алгоритм «mod 10«. Можно передавать тип или типы кредитных карт, известные системе типы карт хранятся в system/config/credit_cards.php. Пример:

    $valid->add_rules('card_num', 'credit_card[american express, mastercard]');

  • phone. Проверка номера телефона. Проверяется только длина номера (отбрасываются все символы, кроме чисел), для чего можно передать массив допустимых длин, по умолчанию берется [7, 10, 11].
  • alpha. Поле должно содержать только буквы алфавита. Необязательный параметр — режим UTF-8 (т.е. символы в UTF-8 виде), по умолчанию FALSE.
  • alpha_numeric. Поле должно содержать только буквы и цифры. Необязательный параметр режим UTF-8.
  • alpha_dash. Поле должно состоять только из букв, цифр, знаков подчеркивания и дефисов. Необязательный параметр режим UTF-8.
  • digit. Поле должно состоять из цифр. Необязательный параметр режим UTF-8.
  • numeric. Поле должно быть числом (цифры, тире и разделитель дробной части).
  • standard_text. Значение должно быть текстом (буквы, цифры, пробелы, тире, знаки подчеркивания и пунктуации).
  • decimal. Значение должно быть десятичным числом. Необязательный параметр — формат в виде массива чисел (если одно число, то это количество знаков после запятой, а если больше — то до и после запятой соответственно). Пример:

    $valid->add_rules('price', 'decimal[2]'); // цена с двумя знаками после запятой

  • date. Значение должно быть датой. Просто проверка strtotime($str) !== FALSE.

Как писать свое правило

Правило — это просто публичный (public) метод класса, в котором формируются правила для Validation. В качестве первого параметра указывается объект Validation, далее имя поля. В случае несоответствия правилу необходимо добавлять ошибку с помощью метода add_error(). Пример callback‘а:

public function username_available($id)
{
return !$this->db
->where($this->unique_key($id), $id)
->count_records($this->table_name);
}

Примечание. Тут-то и обнаружилось расхождение с документацией. В callback передается только имя поля. Соответственно негде вызывать метод add_error(). Зато ошибка в случае возврата FALSE из функции записывается системой самостоятельно. В общем, очередная «непонятка» в документации.

Что в итоге? Сам по себе метод validate() возвращает результат проверки — TRUE/FALSE. Массив ошибок доступен через метод errors(), примененный к массиву, который мы передавали в конструктор Validate:

if ($valid->validate()) {
 
// Делаем что-то, все прошло успешно
 
}
 
else {
 
// Не прошли через все правила, выводим пользователю ошибки
 
$errors = $_POST->errors();
 
$olddata = $_POST->as_array();
 
}

Как правило, в случае ошибки валидации пользователю показывают снова ту же последнюю заполненную форму, список ошибок (можно в строковом виде, очень удобно, когда конкретное поле подсвечивается). Не забывайте о заполнении всех полей формы кроме паролей исходными данными (в моем примере это переменная $olddata) — пользователь может уйти с сайта, т.к. заново все вводить не у каждого хватит терпения. Ну и конечно, желательно делать хотя бы первичную проверку (заполнение обязательных полей) еще на стороне клиента средствами JavaScript, это экономит время и трафик.

Google Bookmarks Digg Reddit del.icio.us Ma.gnolia Technorati Slashdot Yahoo My Web News2.ru БобрДобр.ru RUmarkz Ваау! Memori.ru rucity.com МоёМесто.ru Mister Wong

Опубликовано в cправочник.

Теги: , , .


Комментарии (9)

Будьте в курсе обсуждения, подпишитесь на RSS ленту комментариев к этой записи.

  1. ukko-pekka.livejournal.com/ пишет:

    Вау, отличный цикл статей! С них можно начать локализацию документации.

    Спасибо вам!

  2. BIakaVeron пишет:

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

  3. jleft.ru/ пишет:

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

    По поводу javascript — это полезно, особенно для создания дружественного интерфейса, грустно то, что это легко обходится и на сервере данные всеравно приходится обрабатывать

  4. BIakaVeron пишет:

    А ничего грустного, как мне кажется. Все равно еще встречаются пользователи с отключенным JS, поэтому серверную валидацию никто не отменял

  5. cybexx пишет:

    Прошу помощи! Что-то не могу разобраться с валидацией в ORM.

    Проблема вот в чем: в форме много полей, но в проверять мне все поля не нужно, поэтому класс модели такой:

    class firm_Model extends ORM {

    public function validate(array & $array, $save = FALSE)
    {
    $array = Validation::factory($array)
    ->pre_filter(‘trim’)
    ->add_rules(‘rub_id’, ‘required’, ‘is_natural_no_zero’)
    ->add_rules(‘name’, ‘required’);

    return parent::validate($array, $save);
    }
    }

    После того как я в контроллере делаю проверку
    if ($firm->validate ($post))
    {
    $firm->save();
    }
    в объект $firm попадают только те поля которые описаны в function validation для модели.

    Это так и должно быть? Или я чего-то не догоняю…
    Если мне не нужно проверять все поля, что делать?

  6. BIakaVeron пишет:

    В Kohana v2.3 так и должно быть. Из массива загружаются только те поля, которые участвуют в валидации и не указаны в ignored_columns. Для загрузки используйте метод load_values(), например в случае успешного save()

  7. cybexx пишет:

    ничего не понимаю, что не так?

    if ($firm->validate ($post))
    {
    $firm->load_values($post->as_array());
    $firm->save();
    }

    все равно не сохраняются те поля которые не описаны в function validation для модели.

    Что нужно сделать? Не могу я применять required ко всем полям, но если оно заполнено должен сохранить его.

  8. BIakaVeron пишет:

    Если передать массив в метод validate(), он становится объектом класса Validation, лишние значения потеряются. Попробуйте сделать копию массива $post до валидации

  9. cybexx пишет:

    Спасибо вам за желание помочь, но что-то все равно у меня не получается. Создал тему на форуме Kohana
    http://forum.kohanaphp.com/comments.php?DiscussionID=3654



Можно включить подсветку кода: <code><pre lang="">...</pre></code>
Разрешены некоторые HTML теги

или используйте trackback.