Сообщения об ошибках валидации

Комментарии: 9  Просмотры: 17 603

Как вы помните, при валидации данных в случае их несоответствия требуемым критериям образуется массив ошибок вида:

Array
(
    [название поля] => Array
        (
            [0] => название правила
            [1] => дополнительные параметры в виде массива 
        )
)

Естественно сообщения об ошибках в таком «сыром» виде никогда не используются. Перед выводом их нужно обработать. Давайте посмотрим как это делается на примере добавления комментариев. С комментариями мы работали в этом уроке. Сначала немного изменим контроллер comments. Замените старый код:

if($_POST)
{
    $user = Arr::get($_POST, 'user');
    $message = Arr::get($_POST, 'message');
    Model::factory('Comment')->create_comment($article_id, $user, $message);
}

на такой:

    if($_POST)
    {
        $user = trim($_POST['user']);
        $message = trim($_POST['message']);
 
        $post = Validation::factory($_POST);
        $post -> rule('user', 'not_empty')
	    -> rule('user', 'min_length', array(':value', 2))
	    -> rule('user', 'max_length', array(':value', 20))
	    -> rule('email', 'email')
	    -> rule('message', 'not_empty')
	    -> rule('message', 'max_length', array(':value', 100));
 
        if($post -> check())
        {
            Model::factory('Comment')->create_comment($article_id, $user, $message);
        }
        else
        {
            $errors = $post -> errors('comments');
        }

Вот тут и пригодились стандартные правила, которые мы изучали в двух последних уроках. Поле юзера у нас имеет три проверки — на пустоту, минимальную длину (минимум 2 символа) и максимальную длину (максимум 20 символов). Поле емейла я добавил специально, чтобы охватить несколько правил валидации (не забудьте добавить это поле в форму файла view/comments/show.php). Проверка идет только на правильность адреса электронной почты. Если юзер не захочет вводить свой емейл — пусть не вводит, принуждать не будем, но в любом случае запись в базу содержимого этого поля не производится, оно тут исключительно для примера. И последнее поле — поле сообщения. Оно не должно быть пустым (иначе в чем смысл комментария) и еще я наложил ограничение на количество символов, не больше 100. Дай волю, «Войну и мир» будут цитировать. А так — почти Твиттер :)
Тем, кто читает уроки по порядку, я предлагаю пока не обращать особого внимания на строку из кода:

Model::factory('Comment')->create_comment($article_id, $user, $message);

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

$errors = $post -> errors('comments');

До этого в метод errors мы никаких параметров не передавали. Если вывести содержимое массива $errors без передачи параметра comments, мы увидим уже знакомую картину:

Array
(
    [user] => Array
        (
            [0] => not_empty
            [1] => Array
                (
                    [0] => 
                )
        )
 
    [message] => Array
        (
            [0] => not_empty
            [1] => Array
                (
                    [0] => 
                )
        )
)

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

Array
(
    [user] => user must not be empty
    [message] => message must not be empty
)

Данный параметр как раз является названием файла с массивом сообщений об ошибках. Без него массив $errors не обрабатывается и возвращается «как есть». При указании параметра происходит поиск файла с таким же названием в папке messages/ и в этом файле (если он существует) производится поиск ключа массива с названием not_empty (в нашем случае). Если файл или ключ не найден (а поскольку файл мы не создавали, то так и произойдет), аналогичный поиск производится во встроенном в Кохану файле messages/validation.php. Если поиск опять прошел неудачно, вернется такой массив:

Array
(
    [user] => comments.user.not_empty
    [message] => comments.message.not_empty
)

Фактически массив с ошибками, который формируется в случае удачного поиска, почти удовлетворяет нашим требованиям. Осталось только перевести сообщения об ошибках на русский язык. И в следующем уроке мы как раз этим займемся и полностью доделаем нашу форму для комментариев.

<< Назад | Вперед >> | Обсудить на форуме


К записи оставлено 9 коммент.

Спасибо большое за материал, очень все доходчиво! Я
иду по урокам сверху вниз и вдруг ссылка «мы работали в этом уроке» я с этим уроком не работал, он находится ниже может урок «Сообщения об ошибках валидации» разместить ниже урока «Практика по Query Builder» или предупредить пользователей, а то не много не логично.

Да, я видел этот момент и вчера как раз дописал сюда про это. Вообщем-то достаточно пока не обращать внимания на строку

Model::factory('Comment')->create_comment($article_id, $user, $message);

Присоединяюсь к vasya — Изучаю уроки по очереди, дохожу до этого урока и вижу — замените if($_POST) {….} на …
Однако еще не было ни одной формы и но одного обработчика и следовательно меняь нечего. В одном из предыдущих уроков (связанном с комментами) была фраза любуйтесь краткими анонсами статей — но статьи мы тоже еще не добавляли, а только комменты к ним, да комменты отображаются с названием соответствующей статьи, но перейти к ней можно только из адресной строки т.к. самой статьи нет. Пожалуйста, подкорректируйте так, чтобы было понятно при последовательном изучении таких замечательных уроков. Спасибо

Денис, хочу спросить, сталкивались ли вы с такой проблемой: правила для валидации пишу исключительно в моделях, дабы не засорять контроллер, но если ошибки нужны не дефултные, а специальные для каждого поля, а так же для каждого правила, применяющегося к полям, то метод $e->errors(«message_file») ($e — перехваченное исключение ORM_Validation_exception) возвращает ошибки из стандартного файла сообщений validtion.php. По какой-то неизвестной причине валидация из модели не может взять ошибки из УКАЗАННОГО файла, и по псевдониму поля и ошибки «fiel_name.error_name». А вот обычная валидация а-ля validation::factory($_POST) эти ошбики возращает. Ковырялся в ядре, методы errors() написаны для модели и для стандартной валидации по-разному, но в итоге все все равно сводится к инструкции Kohana::message(‘message_file’, ‘field_name.error_name’) и ее производным, которые сначала ищут специфичуескую ошибку, затем дефултную, а после просто берут стандартную из файла validation.php при невозможности найти вышеуказанные. Так вот валидация модели ВСЕГДА возвращает ошибку из фалйа validation.php. Пробоавл прописывать специфические ошибки прямо там — безрезультатно. Надо заставить фреймворк выводить специфичные ошибки через валидацию модели. Как это сделать, так и не понял. Есть мысли на этот счет? Что скажете?

Честно говоря не сталкивался с таким. Интересно.
Надо будет попробовать.

А слона-то я и не заметил!
Вот как это делается:
Инструкция вида $e->errors(‘model’) вернет ошибки из файла messages/model/имя_модели, которая выбросила исключение при авлидации. Т.е. для модели Model_Subscribe $e->errors(‘model’) отдаст ошибки из файла messages/model/subscribe.php. Он сам ищет файл с таким же именем, что и модель, в директории указанной аргументом к errors().
Работает, только если указать этот аргумент. Если не казать — то вернется массив с именами ошибок а-ля ‘not_empty’, ‘email’ и т.п..
Надеюсь, кому-нибудь поможет, и ваш код в контроллерах станет чище! Используйте валидацию в моделях — это удобно.

Наверное вы пропустили две строки:
$user = Arr::get($_POST, ‘user’);
$message = Arr::get($_POST, ‘message’);
Без них не могло найти значения переменных user и message.

Хотя даже правильнее заменить
create_comment($article_id, $user, $message);
на
create_comment($article_id, $_POST['user'], $_POST['message']);

Угу. Выше главное правильно. Надо вместо

$_POST['user'] = trim($_POST['user']);
$_POST['message'] = trim($_POST['message']);

чтобы было

$user = trim($_POST['user']);
$message = trim($_POST['message']);

Сейчас исправлю. Спасибо.



Оставить комментарий или два

Пожалуйста, зарегистрируйтесь для комментирования.