Yii: Добавляем капчу к комментариям у статей, CAPTCHA и не-Ajax Validation (проверка на лету)

Yii: Добавляем капчу к комментариям у статей, CAPTCHA и не-Ajax Validation (проверка на лету) Как отображать CAPTCHA при добавлении комментариев на любую страницу (не контакты, форма обратной связи)? 

Вставляем в файл вида для комментариев - views/comment/_form.php:

    <?php if (extension_loaded('gd')): ?>
        <div class="row">
            <?php echo CHtml::activeLabelEx($model, 'verifyCode') ?>
        <div>
        <?php $this->widget('CCaptcha'); ?>
        <?php echo CHtml::activeTextField($model,'verifyCode'); ?>
        </div>
        <div class="hint">Please enter the letters as they are shown in the image above.
        <br/>Letters are not case-sensitive.</div>
        </div>
    <?php endif; ?>


В models/Comment.php, добавляем:
1. public $verifyCode;
2. в rules() дописываем:

    array('verifyCode', 'captcha', 'allowEmpty'=>!Yii::app()->user->isGuest),

3. В attributeLabels():

    'verifyCode' => 'Verification Code',


В controllers/PostController.php:
1. добавляем функцию actions():

    public function actions()    {
        return array(
            'captcha'=>array(
                'class'=>'CCaptchaAction',
                'backColor'=>0xFFFFFF,
            ),
        );
    }

2. Теперь вроде всё сделано, но капча не показывается. Смотрим в код CCaptcha, в функцию renderImage(), и видим, что url картинки не разрешён в accessRules в PostController. Добавляем правило:

array('allow',
        'actions'=>array('captcha'),
        'users'=>array('*'),
),


Таким образом мы вставим капчу и она будет работать, но при 'enableAjaxValidation'=>false.

Когда включаем Ajax Validation в виде виджета формы добавления комментария, captcha каждый раз при отправке комментария, выдает ошибку несоответствия. Получается, что когда форма верна, капча меняется в фреймворке, но на странице отображается старая капча.

 Мы хотим настроить, чтобы работала динамичная проверка, то смотрим замечания Qiang Xue:

- As described in CActiveForm, you shouldn't use ajax validation when the validationwould change server side state. The CAPTCHA implementation uses session to store thenumber of tests that have been attempted. This should be considered as server sidestate. If you want to limit the test limit, you should not use ajax validationbecause it simply doesn't make sense. If you want to use ajax validation, you shouldset the test limit to be unlimited.

- How to set the limit to be unlimited? setting testlimit to zero,"-1" or a big number?

- set testLimit to be 0 or negative value

P.S. Ура! Теперь мы разобрались как делать Ajax'овую проверку вместе с Captcha (читайте тут).


almix
Разработчик Loco, автор статей по веб-разработке на Yii, CodeIgniter, MODx и прочих инструментах. Создатель Team Sense.

Вы можете почитать все статьи от almix'а.



Другие статьи по этой теме:

Комментарии (4)     Подпишитесь на RSS комментариев к этой статье.

4 комментариев

#423
IVAN86 говорит:
April 10, 2012 at 10:04 am

Не понятно куда, что добавляем:

2. Теперь вроде всё сделано, но капча не показывается. Смотрим в код CCaptcha, в функцию renderImage(), и видим, что url картинки не разрешён в accessRules в PostController. Добавляем правило:

Поясните пожалуйста.

#424
almix говорит:
April 10, 2012 at 05:52 pm
в контроллере, у меня это PostController.php, вверху есть метод accessRules.  В него и надо вписать код, разрешающий выполнение action "captcha" для этого контроллера для всех пользователей (незарегистрированных в общем случае).
#578
Виталий говорит:
July 17, 2012 at 01:25 pm

в контроллере, у меня это PostController.php, вверху есть метод accessRules.  В него и надо вписать код, разрешающий выполнение action "captcha" для этого контроллера для всех пользователей (незарегистрированных в общем случае).

Сделал всё как тут сказано, но картинка появляется только для зарегистрированных пользователей.


#599
almix говорит:
August 2, 2012 at 01:30 pm

Виталий, проверяйте accessRules

array('allow',
        'actions'=>array('captcha'),
        'users'=>array('*'), //!!!!!
),