16 KiB
Валидация
С использованием [Validate] класса можно произвести валидацию любого массива. По ключу значения массива ("наименование поля" для валидатора), к объекту валидации можно добавить ярлыки, фильтры, правила и функции обратного вызова.
- labels (ярлыки)
- Ярлык - это удобочитаемая интерпретация имени поля.
- filters (фильтры)
- Фильтр видоизменяет значение поля перед применением к нему правил и функций обратного вызова.
- rules (правила)
- Правило - это проверка значения поля, которая возвращает
TRUE
илиFALSE
в результате проверки. Если правило возвращаетFALSE
, то полю будет добавлена информация об ошибке. - callbacks (функция обратного вызова)
- Функция обратного вызова - это пользовательский метод, который имеет доступ до содержания объекта валидации. Возвращаемое значение функции игнорируется, ввиду этого, функция должна сама добавлять ошибку к полу объекта валидации, используя метод [Validate::error], при возникновении ошибки.
[!!] Заметьте, что функции обратного вызова объекта [Validate] и функции обратного вызова PHP (PHP callbacks) - это не одно и то же.
Если вместо имени поля при добавлении фильтра, правила или функции обратного вызова использовать значение TRUE
, то этот фильтр, правило или функция будет применена ко всем полям объекта Validate.
В мерах предосторожности, объект [Validate] удалит все поля из массива, которым не присвоен ярлык, фильтр, правило или функция обратного вызова. Это предотвращает доступ до полей, которые не участвуют в валидации.
Создание объекта валидации производится с использованием метода [Validate::factory]:
$post = Validate::factory($_POST);
[!!] Далее в данном руководстве будет использован объект $post
. Как пример, будет рассмотрена валидация регистрации нового пользователя.
Стандартные правила
Класс валидации содержит следующие правила:
Наименование правила | Действие |
---|---|
[Validate::not_empty] | Значение не должно быть пустым |
[Validate::regex] | Проверяется значение на совпадение с регулярным выражением |
[Validate::min_length] | Минимальная длина значения (минимальное количество знаков) |
[Validate::max_length] | Максимальная длина значения (максимальное количество знаков) |
[Validate::exact_length] | Длина значения должна быть равна указанному числу |
[Validate::email] | Значение должно представлять собой emal адрес |
[Validate::email_domain] | Проверяет существование email домена |
[Validate::url] | Значение должно представлять собой URL |
[Validate::ip] | Значение должно представлять собой IP адрес |
[Validate::phone] | Значение должно представлять собой номер телефона |
[Validate::credit_card] | Значение должно представлять собой номер кредитной карты |
[Validate::date] | Значение должно представлять собой дату (и время) |
[Validate::alpha] | Допустимы только буквенные значения |
[Validate::alpha_dash] | Допустимы значения, состоящие из букв и тире |
[Validate::alpha_numeric] | Допустимы только буквенные и числовые значения |
[Validate::digit] | Значение должно представлять собой целое число |
[Validate::decimal] | Значение должно представлять собой число десятичное число или число с плавающей точкой |
[Validate::numeric] | Допустимы только цифровые символы |
[Validate::range] | Значение должно быть в указанных пределах |
[Validate::color] | Значение должно представлять собой правильное значение цвета в HEX |
[Validate::matches] | Значение должно совпадать со значением другого поля |
[!!] Любой метод [Validate] класса может быть использован как правило валидации без определения полного обратного вызова (callback). Например, добавление 'not_empty'
- то же самое, что и array('Validate', 'not_empty')
.
Добавление фильтров
Фильтр валидации задаётся как имя поля, метод или функция (используя синтаксис PHP callback) и массив параметров:
$object->filter($field, $callback, $parameters);
Фильтры изменяют значение поля перед проверкой правилами или функциями обратного вызова.
Для того, чтобы конвертировать значение поля "username" в нижний регистр:
$post->filter('username', 'strtolower');
Если мы хотим удалить все пробелы до и после значения у всех полей:
$post->filter(TRUE, 'trim');
Добавление правил
Все правила валидации задаются как имя поля, метод или функция (используя синтаксис PHP callback) и массива параметров:
$object->rule($field, $callback, $parameters);
Для начала, инициируем валидацию $_POST
массива, который содержит информацию о регистрации:
$post = Validate::factory($_POST);
Далее, нам необходимо обработать полученные данные, используя [Validate] класс. Во-первых, добавим несколько правил:
$post
->rule('username', 'not_empty')
->rule('username', 'regex', array('/^[a-z_.]++$/iD'))
->rule('password', 'not_empty')
->rule('password', 'min_length', array('6'))
->rule('confirm', 'matches', array('password'))
->rule('use_ssl', 'not_empty');
В виде правила можно использовать практически все функции PHP. Например, можно проверить, верное ли значение ввёл пользователь на SSL вопрос:
$post->rule('use_ssl', 'in_array', array(array('yes', 'no')));
Имейте в виду, что все параметры должны быть в виде массива! Если параметры были не в виде массива, то функция in_array
была бы вызвана как in_array($value, 'yes', 'no')
, что привело бы к PHP ошибке.
Пользовательские правила могут быть добавлены, используя синтаксис PHP callback:
$post->rule('username', array($model, 'unique_username'));
Метод $model->unique_username()
определяется следующим образом:
public function unique_username($username)
{
// Проверка на то, имеется ли указанное значение username в БД
return ! DB::select(array(DB::expr('COUNT(username)'), 'total'))
->from('users')
->where('username', '=', $username)
->execute()
->get('total');
}
[!!] Пользовательские правила позволяют производить большое количество дополнительных проверок и могут быть использованы для различных целей множество раз. Зачастую, они создаются как методы модели, однако, если необходимо, могут быть определены в любом классе.
Добавление функций обратного вызова (callbacks)
Все функции обратного вызова (callback) определяются как имя поля, метод или функция (используя синтаксис PHP callback) и массива параметров:
$object->callback($field, $callback, $parameters);
[!!] До версии kohana 3.0.7, функции обратного вызова не обрабатывали входных параметров, в отличие от фильтров и правил. Если Вы используете старую версию, эти параметры будут проигнорированы.
Пароль пользователя должен быть захэширован, если он прошёл валидацию, поэтому это можно сделать, используя функцию обратного вызова:
$post->callback('password', array($model, 'hash_password'));
Это подразумевает, что метод $model->hash_password()
будет работать следующим образом:
public function hash_password(Validate $array, $field)
{
if ($array[$field])
{
// Хэшировать пароль, если он присутствует
$array[$field] = sha1($array[$field]);
}
}
Полный пример
Во-первых, нам понадобится представление ([View]), которое содержит HTML форму и которое будет располагаться в application/views/user/register.php
:
<?php echo Form::open() ?>
<?php if ($errors): ?>
<p class="message">Были допущены следующие ошибки:</p>
<ul class="errors">
<?php foreach ($errors as $message): ?>
<li><?php echo $message ?></li>
<?php endforeach ?>
<?php endif ?>
<dl>
<dt><?php echo Form::label('username', 'Имя пользователя') ?></dt>
<dd><?php echo Form::input('username', $post['username']) ?></dd>
<dt><?php echo Form::label('password', 'Пароль') ?></dt>
<dd><?php echo Form::password('password') ?></dd>
<dd class="help">Пароль должен быть длиной как минимум в 6 знаков.</dd>
<dt><?php echo Form::label('confirm', 'Подтверждение пароля') ?></dt>
<dd><?php echo Form::password('confirm') ?></dd>
<dt><?php echo Form::label('use_ssl', 'Используете дополнительное шифрование?') ?></dt>
<dd><?php echo Form::select('use_ssl', array('yes' => 'Всегда', 'no' => 'По необходимости'), $post['use_ssl']) ?></dd>
<dd class="help">В целях безопасности, при проведении платежей всегда используется протокол SSL.</dd>
</dl>
<?php echo Form::submit(NULL, 'Создать') ?>
<?php echo Form::close() ?>
[!!] В этом примере повсеместно используется хелпер [Form]. Использование [Form] вместо формирования HTML кода формы вручную, гарантирует корректную обработку входящих данных. Если Вы предпочитаете писать HTML собственноручно, используйте метод [HTML::chars], чтобы обезопасить приложение от введённых пользователем данных.
Во-вторых, нам потребуется контроллер и действие этого контроллера, чтобы произвести регистрацию, которые будут располагаться в файле application/classes/controller/user.php
:
class Controller_User extends Controller {
public function action_register()
{
$user = Model::factory('user');
$post = Validate::factory($_POST)
->filter(TRUE, 'trim')
->filter('username', 'strtolower')
->rule('username', 'not_empty')
->rule('username', 'regex', array('/^[a-z_.]++$/iD'))
->rule('username', array($user, 'unique_username'))
->rule('password', 'not_empty')
->rule('password', 'min_length', array('6'))
->rule('confirm', 'matches', array('password'))
->rule('use_ssl', 'not_empty')
->rule('use_ssl', 'in_array', array(array('yes', 'no')))
->callback('password', array($user, 'hash_password'));
if ($post->check())
{
// Данные прошли проверку, теперь можно зарегистрировать пользователя
$user->register($post);
// Всегда делайте редирект после успешного POST запроса, чтобы избежать
// повторного ввода информации при обновлении страницы
$this->request->redirect('user/profile');
}
// Валидация не прошла, собираем ошибки
$errors = $post->errors('user');
// Отображаем форму регистрации
$this->request->response = View::factory('user/register')
->bind('post', $post)
->bind('errors', $errors);
}
}
Так же нам потребуется модель пользователя, которую поместим в application/classes/model/user.php
:
class Model_User extends Model {
public function register($array)
{
// Создание нового пользователя в БД
$id = DB::insert(array_keys($array))
->values($array)
->execute();
// Сохраняем id нового пользователя в cookie
cookie::set('user', $id);
return $id;
}
}
Вот и всё, у нас имеется готовый пример для регистрации пользователя, который правильно проверяет введённые пользователем данные!