Валидация формы: Пост и Пре.

Главные вкладки

Аватар пользователя beliy_snow beliy_snow 21 марта 2007 в 18:46

Добрались до форм, точнее до их проверки, то есть валидации, если быть правильным. Вообще валидация в вебе - дело серьезное и т.к. мы работаем с формами, то делится она на 2 части. Пре- и поствалидация.

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

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

Превалидация.
Допустим, у вас есть модуль, который выполняет нужный вам функционал, не важно какой, но важно, что этот функционал влияет на отображение контента, в частности на ноду. Сегодня обойдемся без примеров, так что придумайте сами где это можно применить. Итак. Назовем модуль... а пофиг, так и назовем - "my_module". Чтобы отредактировать ноду - надо создать форму с полями и кнопками, т.е. вызвать функцию "node_form()". Кто не знает что такое хуки - поздравляю, щас узнаете. Друпал писали умные люди и предусмотрели возможность изменения формы редактирования ноды путем применения хуков, а именно хука "form_alter()". Т.е. как только создали форму для ноды - отдаем эту форму на растерзание тем модулям, у которых есть функция "имя_модуля_form_alter()". Если в вашем "my_module" нет такой функции - создаем.

<?php function my_module_form_alter($form_id, &$form) {
if ($form_id == 'comment_form') {
// мы получили форму отправки комментария, чтобы посмотреть как выглядит форма в виде массива - пишем:
print_r($form);
// в параметрах замечаем - &$form - получили форму не по ссылке, а по значению, т.е. имеем полное право извращаться
...
// теперь нам надо указать функцию, которая будет обеспечивать нашу Поствалидацию, пишем:
$form['#validate']['my_module_form_validate'] = array();
}
elseif ($form_id == 'node_delete_confirm')
{
// получили форму подтверждения удаления ноды, так же можем извращаться, но не забудем в конце указать функцию поствалидации
...
$form['#validate']['my_module_form_validate'] = array();
}
}?>

Поствалидация.
Поствалидацию, как и все остальное, обеспечивают функции. Нашу валидирующую функцию мы указали выше, осталось её написать.

<?php function my_module_form_validate($form_id, $form_values, $form) {
if ($form_id == 'comment_form') {
// например я не хочу, чтобы умник оставлял комментарии больше 2-го уровня вложенности
$parent_depth = (count(explode('.', db_result(db_query("SELECT thread FROM {comments} WHERE cid = %d", $form_values['pid'])))) - 1);
if ($parent_depth >= 1)
{
form_set_error($form_id, 'You can not leave comment!
' . l('Cancel', 'node/'.$form_values['nid']));
}
}
elseif ($form_id == 'node_delete_confirm') {
// тут примера нет, можно просто скажем челу, что нельзя так делать
form_set_error($form_id, "You have no rights to delete this Article.");
drupal_goto('node/'.$nid);
}
}?>

Замечания. Кроме формы можно превалидировать и линки, например для комментариев. Но че-то как-то не особо получилось поработать с хуком "link_alter" ибо там глюк какой-то и все советуют править в модуле, поэтому пришлось писать валидацию прям в коде модуля "comment". Как и в верхнем примере с поствалидацией я не хочу, чтобы у комментариев второго уровня показывалась ссылка "Reply". Поэтому лезу в код функции "comment_links()" и правлю наживую.

<?php function comment_links($comment, $return = 1) {
...
// отображаю ссылку, только если глубина коммента меньше 1
if ($comment->depth < 1) {
$links['comment_reply'] = array(
'title' => t('reply'),
'href' => "comment/reply/$comment->nid/$comment->cid"
);
}
}?>

Это тоже превалидация.

Comments and suggestions are welcome.