243 lines
16 KiB
Markdown
243 lines
16 KiB
Markdown
|
# Валидация
|
|||
|
|
|||
|
С использованием [Validate] класса можно произвести валидацию любого массива. По ключу значения массива ("наименование поля" для валидатора), к объекту валидации можно добавить ярлыки, фильтры, правила и функции обратного вызова.
|
|||
|
|
|||
|
labels (ярлыки)
|
|||
|
: Ярлык - это удобочитаемая интерпретация имени поля.
|
|||
|
|
|||
|
filters (фильтры)
|
|||
|
: Фильтр видоизменяет значение поля перед применением к нему правил и функций обратного вызова.
|
|||
|
|
|||
|
rules (правила)
|
|||
|
: Правило - это проверка значения поля, которая возвращает `TRUE` или `FALSE` в результате проверки. Если правило возвращает `FALSE`, то полю будет добавлена информация об ошибке.
|
|||
|
|
|||
|
callbacks (функция обратного вызова)
|
|||
|
: Функция обратного вызова - это пользовательский метод, который имеет доступ до содержания объекта валидации. Возвращаемое значение функции игнорируется, ввиду этого, функция должна сама добавлять ошибку к полу объекта валидации, используя метод [Validate::error], при возникновении ошибки.
|
|||
|
|
|||
|
[!!] Заметьте, что функции обратного вызова объекта [Validate] и функции обратного вызова PHP ([PHP callbacks](http://php.net/manual/language.pseudo-types.php#language.types.callback)) - это не одно и то же.
|
|||
|
|
|||
|
Если вместо имени поля при добавлении фильтра, правила или функции обратного вызова использовать значение `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](http://ru2.php.net/callback)) и массив параметров:
|
|||
|
|
|||
|
$object->filter($field, $callback, $parameters);
|
|||
|
|
|||
|
Фильтры изменяют значение поля перед проверкой правилами или функциями обратного вызова.
|
|||
|
|
|||
|
Для того, чтобы конвертировать значение поля "username" в нижний регистр:
|
|||
|
|
|||
|
$post->filter('username', 'strtolower');
|
|||
|
|
|||
|
Если мы хотим удалить все пробелы до и после значения у *всех* полей:
|
|||
|
|
|||
|
$post->filter(TRUE, 'trim');
|
|||
|
|
|||
|
## Добавление правил
|
|||
|
|
|||
|
Все правила валидации задаются как имя поля, метод или функция (используя синтаксис [PHP callback](http://ru2.php.net/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](http://ru2.php.net/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](http://ru2.php.net/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;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
Вот и всё, у нас имеется готовый пример для регистрации пользователя, который правильно проверяет введённые пользователем данные!
|