Фреймворк — штука удобная. Нужна форма? Нет проблем. Создал таблицу в базе данных, запустил генератор кода и вуаля! Приложение уже готово взаимодействовать с пользователем по всем фронтам.
А уж если в фреймворк встроена валидация, которая проверит введенные данные (хорошо бы через ajax запрос, а не только через сабмит) и сообщит пользователю сайта об ошибках, то на душе становится совсем уж привольно.
Сегодня речь пойдет о фреймворке Yii, а конкретно о валидации форм, ну уж совсем конкретно — о проблеме совместимости капчи и ajax, при валидации. Дело в том, что после того как форма показана пользователю, при любом ajax-запросе, капча изменяется внутри фреймворка, в то время как на странице остается оригинальное изображение. В итоге, когда форма заполнена и отправлена на сервер, валидация заканчивается неудачей.
Эта проблема не раз обсуждалась на профильных форумах и в баг-трекере. В итоге лучшее, что могут предложить авторы фреймворка — установить неограниченное количество показов одной и той же капчи пользователю. Решение, прямо сказать, не логичное. Любой робот, однажды распознав капчу, сможет сколько угодно бродить по сайту и оставлять сообщения, гадить в комментариях или того хуже — подбирать пароли пользователей перебором.
Как оказалось решение проблемы не такое сложное, если не сказать — банальное.
В первую очередь необходимо создать новый валидатор activeCaptcha, который будет пользоваться стандартным контроллером класса Captcha.
Данный валидатор при каждом вызове проверяет, соответствует ли код с картинки, коду который ввел пользователь. Затем, если валидатор вызван не посредством ajax запроса, код капчи обновляется.
После этого необходимо задать правила валидации для атрибутов модели (используя валидатор «activeCaptcha» вместо «captcha»):
Если у вас отключена ajax-валидация форм, то теперь ее можно включить.
В представлении (view) пишем:
И в контролере:
Теперь можно запустить веб-приложение и увидеть, что все работает как надо:
капча обновляется при каждом обновлении страницы и после сабмита формы. При этом при заполнении формы капча ведет себя культурно и пользователь может воспользоваться ей без всяких проблем.
А уж если в фреймворк встроена валидация, которая проверит введенные данные (хорошо бы через ajax запрос, а не только через сабмит) и сообщит пользователю сайта об ошибках, то на душе становится совсем уж привольно.
Сегодня речь пойдет о фреймворке Yii, а конкретно о валидации форм, ну уж совсем конкретно — о проблеме совместимости капчи и ajax, при валидации. Дело в том, что после того как форма показана пользователю, при любом ajax-запросе, капча изменяется внутри фреймворка, в то время как на странице остается оригинальное изображение. В итоге, когда форма заполнена и отправлена на сервер, валидация заканчивается неудачей.
Эта проблема не раз обсуждалась на профильных форумах и в баг-трекере. В итоге лучшее, что могут предложить авторы фреймворка — установить неограниченное количество показов одной и той же капчи пользователю. Решение, прямо сказать, не логичное. Любой робот, однажды распознав капчу, сможет сколько угодно бродить по сайту и оставлять сообщения, гадить в комментариях или того хуже — подбирать пароли пользователей перебором.
Как оказалось решение проблемы не такое сложное, если не сказать — банальное.
В первую очередь необходимо создать новый валидатор activeCaptcha, который будет пользоваться стандартным контроллером класса Captcha.
public function activeCaptcha() {
$code = Yii::app()->controller->createAction('captcha')->getVerifyCode();
if ($code != $this->verifyCode)
$this->addError('verifyCode', 'Неправильный код проверки.');
if (!(isset($_POST['ajax']) && $_POST['ajax']==='user-form'))
Yii::app()->controller->createAction('captcha')->getVerifyCode(true);
}
Данный валидатор при каждом вызове проверяет, соответствует ли код с картинки, коду который ввел пользователь. Затем, если валидатор вызван не посредством ajax запроса, код капчи обновляется.
После этого необходимо задать правила валидации для атрибутов модели (используя валидатор «activeCaptcha» вместо «captcha»):
array('verifyCode', 'activeCaptcha', 'on'=>'register')
Если у вас отключена ajax-валидация форм, то теперь ее можно включить.
В представлении (view) пишем:
$form=$this->beginWidget('CActiveForm', array(
'id'=>'user-form',
'enableAjaxValidation'=>true,
));
И в контролере:
$this->performAjaxValidation($model);
Теперь можно запустить веб-приложение и увидеть, что все работает как надо:
капча обновляется при каждом обновлении страницы и после сабмита формы. При этом при заполнении формы капча ведет себя культурно и пользователь может воспользоваться ей без всяких проблем.