Думаю, для многих из нас фраза «валидация форм» является синонимом кучи дополнительного проверочного кода в контроллерах, длительной настройки всевозможных плагинов валидации, и так далее. Да, современный мир предлагает множество самых разных решений этой проблемы, как на клиентской стороне, так и на серверной. Но если честно, говоря о клиентской валидации… какие-то все эти библиотеки слишком громоздкие и неповоротливые, настолько, что у меня каждый раз отбивало желание подключать их к своим проектам.
Поэтому я и решил в конце-концов собрать весь код, который я писал в проектах, и скомпоновать его в одну небольшую библиотеку под названием PrettyForms. Библиотека эта содержит совсем немного кода, но при этом задачу свою она уже сейчас неплохо решает.
Пример работы библиотеки:
PrettyForms изначально заточена под сайты, созданные на основе Twitter Bootstrap, но вы легко можете заменить её шаблоны с собщениями об ошибках на свои собственные, переопределив три переменных в объекте "PrettyForms.templates".
Весь исходный код достаточно подробно прокомментирован, так как мной предполагается, что другие люди захотитят изменить логику работы каких-то частей библиотеки и доработать её под свои личные нужды, так как из коробки она имеет довольно скромный и минималистичный функционал, который был необходим лично мне для работы моих проектов.
Самый простой вариант
Чтобы она просто начала работать, необходимо лишь подключить её к странице, а после этого добавить для всех полей, для которых необходима валидация, атрибут «data-validation», содержащий правила валидации, описанные на странице библиотеки в разделе «Валидаторы полей».
Всё. Больше ничего делать не надо, всё остальное библиотека сделает за вас :) К этому я и стремился изначально: как можно меньше телодвижений.
Это самый простой вариант, без учёта серверной валидации данных. Если же у вас появилось желание использовать все возможности PrettyForms, тогда вам следует изучить алгоритм работы и протокол общения клиентской машины с сервером, благодаря которому она и становится столь удобной в использовании.
Вариант с клиент-серверной валидацией
Алгоритм работы:
- Когда пользователь вводит данные в форму, библиотека проверяет данные и оповещает об ошибках, если они возникли.
- Пользователь нажимает кнопку отправки формы. Библиотека снова проводит валидацию всех данных, и если всё нормально, она собирает все данные формы, отправляет POST-запрос на сервер и ожидает от него JSON-ответ в специальном формате.
- Сервер, получив запрос, проводит дополнительную валидацию данных уже на своей стороне. Если возникли ошибки при серверной валидации, он возвращает клиенту специальным образом сформированный JSON-ответ, содержащий команду для отображения ошибок серверной валидации с информацией о полях и содержащихся в них ошибках.
- Если данные успешно прошли валидацию и на сервере, сервер производит необходимые операции и возвращает JSON-ответ с командами, описывающими действия, которые клиентская машина должна выполнить после успешного выполнения операции.
То есть, сервер всегда отвечает определённым набором команд для браузера, а браузер просто исполняет данные команды на клиенской машине. Таков алгоритм работы библиотеки. Более подробное описание протокола можно найти на странице библиотеки в разделе «Формат протокола общения клиента с сервером».
Для того чтобы настроить библиотеку для работы с сервером, добавьте к вашей стандартной кнопке отправки формы класс senddata, благодаря которому клики по кнопке будут перехвачены и обработаны библиотекой. Теперь библиотека не только будет производить клиентскую валидацию, но и станет отвечать за отправку данных на сервер и обработку ответа.
Пример формы для Bootstrap-фреймворка с атрибутами валидации:
<form class="form-horizontal" role="form" method="POST">
<h1 class="form-signin-heading">Регистрация</h1>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="email"
class="form-control"
id="inputEmail3"
name="email"
data-validation="notempty;isemail"
placeholder="Введите ваш email">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Пароль</label>
<div class="col-sm-10">
<input
type="password"
class="form-control"
id="inputPassword3"
name="password"
data-validation="notempty;minlength:6"
placeholder="Ваш пароль">
</div>
</div>
<div class="form-group">
<label for="inputPassword4" class="col-sm-2 control-label">Повторите пароль</label>
<div class="col-sm-10">
<input type="password"
class="form-control"
id="inputPassword4"
name="password_retry"
data-validation="notempty;passretry"
placeholder="Повторите пароль, вдруг ошиблись при вводе? Мы проверим это.">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div type="submit"
data-input=".form-horizontal"
data-link="<?=URL::to('register')?>"
data-clearinputs="true"
class="btn btn-default senddata">Зарегистрироваться</div>
</div>
</div>
</form>
Теперь, кликая по кнопке «Зарегистрироваться», мы заставим библиотеку проверить данные формы на валидность, а после этого отправить их на сервер и обработать ответ.
Валидация на сервере
Валидацией на сервере должен заниматься тот фреймворк, с которым вы работаете. Библиотека лишь предоставляет класс, упрощающий создание корректного JSON-ответа с командами для клиента.
Но для фреймворка Laravel мною были созданы специальные классы, благодаря которым работа библиотеки в данном фреймворке сводится к дописыванию нескольких строк кода, после чего валидация начинает работать и на сервере.
Чтобы включить валидацию для какого-либо контроллера и модели Laravel, подключите к нужной модели трейт для подключения функционала валидации, а также опишите в ней массив с правилами валидации для полей:
use PrettyFormsLaravelValidatorTrait;
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait, LaravelValidatorTrait;
//...
private $rules = [
'email' => 'required|email|unique:users,email',
'password' => 'required|min:6'
];
}
После этого, в коде обработки запроса, вам остается лишь добавить данный код, который автоматически будет производить валидацию данных перед отправкой, и если что-то пойдёт не так, выполнение будет остановлено, а клиенту будет отправлен ответ с командой отображения ошибок валидации сервера.
use PrettyFormsLaravelResponse;
//...
$user = new User;
$user->email = Input::get('email');
$user->password = Hash::make(Input::get('password'));
$user->validateAndSave();
// Ошибок валидации не произошло, генерируем ответ с одной командой: редирект пользователя
return LaravelResponse::generate([
'redirect' => '/login'
]);
Метод LaravelResponse::generate принимает ассоциативный массив из команд и их параметров, которые будут выполнены на клиенской машине. Изначально библиотека поддерживает лишь две команды: validation_errors и redirect. Первая команда используется библиотекой для отправки ошибок формы, вторая — для редиректа пользователя в другое место. Вы можете легко расширить функционал библиотеки, добавив свои собственные обработчики команд, посмотрев на примеры того, как это сделано в оригинальном коде библиотеки.
В общем-то, на этом — всё. Вот таким простым образом можно реализовать валидацию на клиенте и сервере без излишней головной боли, настройки гиганстких плагинов, написания кучи кода в контроллерах, и так далее) Надеюсь, эта библиотека поможет кому-то еще, и я не зря писал весь этот текст)
Проблемы
Библиотека не представляет из себя решение на все случаи жизни и не нацелена на подобное развитие. Это скорее небольшая заготовка, которую вы можете использовать и дорабатывать под свои нужды в своих собственных проектах.
В данный момент, одна из проблем — это невозможность собирать инпуты с теми типами, которые были описаны в стандартах HTML5, хотя их поддержку можно легко добавить в библиотеку, но в данный момент у меня просто не возникало данной необходимости.
Одна из частых проблем — это трудности с получением содержимого из тех полей, к которым применён какой-то дополнительный плагин, вроде Chosen или CKEDitor. Конкретно для двух этих плагинов в библиотеке уже встроена поддержка, и она корректно получает значения из полей, связанных с данными плагинами, но в мире существуют тысячи других плагинов, с которыми она может работать некорректно. Следует учитывать это при использовании библиотеки.
Автор: saggid