Yii Captcha не показывает изображение внутри модуля, работает на siteController

Я использую модуль управления пользователями Yii, когда я регистрируюсь на моем веб-сайте, изображение капчи не отображается в форме, однако в контактной форме, созданной Yii, капча отображается. Вот мой взгляд

РЕДАКТИРОВАТЬ: когда я использую инструменты разработчика firebug или chrome, я вижу, что ссылка работает нормально, даже если я обновляю ее, код меняется, но изображение не печатается, но img и его атрибут находятся в файле html.

<?php $this->breadcrumbs = array(Yum::t('Registration')); ?>
<div class="form">
<?php $activeform = $this->beginWidget('CActiveForm', array(
        'id'=>'registration-form',
        'enableAjaxValidation'=>true,
        'enableClientValidation'=>true,
        'focus'=>array($form,'username'),
        ));
?>

<?php echo Yum::requiredFieldNote(); ?>
<?php echo CHtml::errorSummary(array($form, $profile)); ?>

<div class="row"> <?php
echo $activeform->labelEx($form,'username');
echo $activeform->textField($form,'username');
?> </div>

<div class="row">
<?php
echo $activeform->labelEx($profile,'email');
echo $activeform->textField($profile,'email');
?> </div>  

<div class="row"> <?php
echo $activeform->labelEx($profile,'firstname');
echo $activeform->textField($profile,'firstname'); 
?> </div>  

    <div class="row"> <?php
   echo $activeform->labelEx($profile,'lastname');
   echo $activeform->textField($profile,'lastname');
   ?> </div>  

<div class="row">
<?php echo $activeform->labelEx($form,'password'); ?>
<?php echo $activeform->passwordField($form,'password'); ?>
</div>

<div class="row">
<?php echo $activeform->labelEx($form,'verifyPassword'); ?>
<?php echo $activeform->passwordField($form,'verifyPassword'); ?>
</div>

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

<div class="row submit">
    <?php echo CHtml::submitButton(Yum::t('Registration')); ?>
</div>

<?php $this->endWidget(); ?>
</div><!-- form -->

вот мой контроллер

<?php
/* This file handles a example registration process logic and some of the
* most used functions for Registration and Activation. It is recommended to
* extend from this class and implement your own, project-specific 
* Registration process. If this example does exactly what you want in your
* Project, then you can feel lucky already! */

Yii::import('application.modules.user.controllers.YumController');
Yii::import('application.modules.user.models.*');
Yii::import('application.modules.profile.models.*');
Yii::import('application.modules.registration.models.*');

class YumRegistrationController extends YumController {
  public $defaultAction = 'registration';

// Only allow the registration if the user is not already logged in and
// the function is activated in the Module Configuration
public function beforeAction($action) {
    if (!Yii::app()->user->isGuest) 
        $this->redirect(Yii::app()->user->returnUrl);

    $this->layout = Yum::module('registration')->layout;
    return parent::beforeAction($action);
}

public function accessRules() {
    return array(
            array('allow',
                'actions' => array('index', 'registration', 'recovery', 'activation','captcha', 'resendactivation'),
                'users' => array('*'),
                ),
            array('deny', // deny all other users
                'users' => array('*'),
                ),
            );
}

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

/*
 * an Example implementation of an registration of an new User in the system.
 *
 * please see the documentation of yii-user-management for examples on how to
 * extend from this class and implement your own registration logic in
 * user/docs/registration.txt
 */
public function actionRegistration() {
    // When we overrie the registrationUrl, this one is not valid anymore!
    if(Yum::module('registration')->registrationUrl != array(
                '//registration/registration/registration'))
        throw new CHttpException(403);

    Yii::import('application.modules.profile.models.*');
    $form = new YumRegistrationForm;
    $profile = new YumProfile;

    $this->performAjaxValidation('YumRegistrationForm', $form);

    if (isset($_POST['YumRegistrationForm'])) { 
        $form->attributes = $_POST['YumRegistrationForm'];
        $profile->attributes = $_POST['YumProfile'];

        $form->validate();
        $profile->validate();

        if(!$form->hasErrors() && !$profile->hasErrors()) {
            $user = new YumUser;
            $user->register($form->username, $form->password, $profile->email);
            $profile->user_id = $user->id;
            $profile->save();

            $this->sendRegistrationEmail($user);
            Yum::setFlash('Thank you for your registration. Please check your email.');
            $this->redirect(Yum::module()->loginUrl);
        }
    } 

    $this->render(Yum::module()->registrationView, array(
                'form' => $form,
                'profile' => $profile,
                )
            );  
}

// Send the Email to the given user object. $user->email needs to be set.
public static function sendRegistrationEmail($user) {
    if (!isset($user->profile->email)) {
        throw new CException(Yum::t('Email is not set when trying to send Registration Email'));
    }
    $activation_url = $user->getActivationUrl();

    // get the text to sent from the yumtextsettings table
    $content = YumTextSettings::model()->find('language = :lang', array(
                'lang' => Yii::app()->language));
    $sent = null;

    if (is_object($content)) {
        $body = strtr($content->text_email_registration, array(
                    '{username}' => $user->username,
                    '{activation_url}' => $activation_url));

        $mail = array(  'from_name'=>Yii::app()->name,
                'from' => Yum::module('registration')->registrationEmail,
                'to' => $user->profile->email,
                'to_name'=>$user->profile->firstname,
                'subject' => strtr($content->subject_email_registration, array(
                        '{username}' => $user->username)),
                'body' => $body,
                );
        $sent = YumMailer::send($mail);
    }
    else {
        throw new CException(Yum::t('The messages for your application language are not defined.'));
    }

    return $sent;
}

/**
 * Activation of an user account. The Email and the Activation key send
 * by email needs to correct in order to continue. The Status will
 * be initially set to 1 (active - first Visit) so the administrator
 * can see, which accounts have been activated, but not yet logged in 
 * (more than once)
 */
public function actionActivation($email, $key) {
    // If already logged in, we dont activate anymore
    if (!Yii::app()->user->isGuest) {
        Yum::setFlash('You are already logged in, please log out to activate your account');
        $this->redirect(Yii::app()->user->returnUrl);
    }

    // If everything is set properly, let the model handle the Validation
    // and do the Activation
    $status = YumUser::activate($email, $key);


    if($status instanceof YumUser) {
        if(Yum::module('registration')->loginAfterSuccessfulActivation) {
            $login = new YumUserIdentity($status->username, false); 
            $login->authenticate(true);
            Yii::app()->user->login($login);    
        } 

        $this->render(Yum::module('registration')->activationSuccessView);
    }
    else
        $this->render(Yum::module('registration')->activationFailureView, array(
                    'error' => $status));
}

/**
 * Password recovery routine. The User will receive an email with an
 * activation link. If clicked, he will be prompted to enter his new
 * password.
 */
public function actionRecovery($email = null, $key = null) {
    $form = new YumPasswordRecoveryForm;

    if ($email != null && $key != null) {
        if($profile = YumProfile::model()->find('email = :email', array(
                        'email' =>  $email))) {
            $user = $profile->user;
            if($user->activationKey == $key) {
                $passwordform = new YumUserChangePassword;
                if (isset($_POST['YumUserChangePassword'])) {
                    $passwordform->attributes = $_POST['YumUserChangePassword'];
                    if ($passwordform->validate()) {
                        $user->password = YumUser::encrypt($passwordform->password);
                        $user->activationKey = YumUser::encrypt(microtime() . $passwordform->password);
                        $user->save();
                        Yum::setFlash('Your new password has been saved.');
                        $this->redirect(Yum::module()->loginUrl);
                    }
                }
                $this->render(
                        Yum::module('registration')->changePasswordView, array(
                            'form' => $passwordform));
                Yii::app()->end();
            } else {
                $form->addError('login_or_email', Yum::t('Invalid recovery key'));
                Yum::log(Yum::t(
                            'Someone tried to recover a password, but entered a wrong recovery key. Email is {email}, associated user is {username} (id: {uid})', array(
                                '{email}' => $email,
                                '{uid}' => $user->id,
                                '{username}' => $user->username)));
            }
        }
    } else {
        if (isset($_POST['YumPasswordRecoveryForm'])) {
            $form->attributes = $_POST['YumPasswordRecoveryForm'];

            if ($form->validate()) {
                Yum::setFlash(
                        'Instructions have been sent to you. Please check your email.');

                if($form->user instanceof YumUser) {
                    $form->user->generateActivationKey();
                    $recovery_url = $this->createAbsoluteUrl(
                            Yum::module('registration')->recoveryUrl[0], array(
                                'key' => $form->user->activationKey,
                                'email' => $form->user->profile->email));

                    Yum::log(Yum::t(
                                '{username} successfully requested a new password in the password recovery form. A email with the password recovery url {recovery_url} has been sent to {email}', array(
                                    '{email}' => $form->user->profile->email,
                                    '{recovery_url}' => $recovery_url,
                                    '{username}' => $form->user->username)));

                    $content = YumTextSettings::model()->find(
                            'language = :lang', array('lang' => Yii::app()->language));
                    $sent = null;

                    if (is_object($content)) {
                        $mail = array(
                                'from' => Yii::app()->params['adminEmail'],
                                'to' => $form->user->profile->email,
                                'subject' => $content->subject_email_registration,
                                'body' => strtr($content->text_email_recovery, array(
                                        '{recovery_url}' => $recovery_url)),
                                );
                        $sent = YumMailer::send($mail);
                    } else {
                        throw new CException(Yum::t('The messages for your application language are not defined.'));
                    }
                } else
                    Yum::log(Yum::t(
                                'A password has been requested, but no associated user was found in the database. Requested user/email is: {username}', array(
                                    '{username}' => $form->login_or_email)));
                $this->redirect(Yum::module()->loginUrl);
            }
        }
    }
 $this->render(Yum::module('registration')->recoverPasswordView, array(
                'form' => $form));
    }
  }

Вот моя модель

<?php
/**
* RegistrationForm class.
* RegistrationForm is the data structure for keeping
* user registration form data. It is used by the 'registration' action of       'YumUserController'.
* @package Yum.models
*/
   class YumRegistrationForm extends YumUser {
public $verifyPassword;

/**
 * @var string
 */
public $verifyCode;

public function rules() 
{
    $rules = parent::rules();
    if(Yii::app()->getModule('user')->loginType != 'LOGIN_BY_EMAIL' || Yum::module()->registrationType ==REG_NO_USERNAME_OR_PASSWORD || Yum::module()->registrationType == REG_NO_USERNAME_OR_PASSWORD_ADMIN)
        $rules[] = array('username', 'required');
    $rules[] = array('password, verifyPassword', 'required');
    $rules[] = array('password', 'compare', 'compareAttribute'=>'verifyPassword', 'message' => Yii::t("UserModule.user", "Retype password is incorrect."));
    $rules[] = array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements(),'on'=>'insert');

    return $rules;


}

public function genRandomString( $length = 10)
{
$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
$string ='';    
for ($p = 0; $p < $length; $p++)
 {
    $string .= $characters[mt_rand(0, strlen($characters)-1)];
}
return $string;
}

  }

person Eliethesaiyan    schedule 12.09.2013    source источник


Ответы (3)


Измените это на это, на ваш взгляд. По умолчанию изображение капчи загружается из SiteController, где капча — это действие (вы можете увидеть его там в разделе «Действия»). Вы имеете в виду //registration/registration/captcha, которого не существует:

<?php $this->widget('CCaptcha', array('captchaAction'=>'site/captcha')); ?>
person davey    schedule 13.09.2013
comment
Спасибо, Дэйви... на самом деле //registration/registration/captcha ссылается на контроллер с именем RegistrationController модуля с именем Registration... он действителен, и я вижу в html, что код изменяется, когда я нажимаю на ссылку, которая генерирует другую код .... я тоже пробовал то, что вы предложили ... изображение отображается, когда дело доходит до проверки ... форма проверяется по модели регистрации ... не той, что с сайтом ..... Любая идея, как я могу проверить капчу против Sites ContactForms captcha и остальных полей модели регистрации...? - person Eliethesaiyan; 13.09.2013
comment
О, извините, вы действительно правы насчет модуля! Можете ли вы привести пример изображения URL-адреса capthca? А название поля ввода капчи (где пользователь вводит код капчи)? - person davey; 16.09.2013
comment
URL-адрес выглядит так в firebug... index.php/registration/registration/ код продолжает меняться, когда я нажимаю, чтобы получить новый код)... текстовое поле для ввода деталей.. вы можете обратиться к файлу просмотра, который я разместил в вопросе.. большое спасибо для вашей помощи - person Eliethesaiyan; 17.09.2013
comment
да..именно там я не вижу никакого изображения..но когда я указываю виджету капчи на сайт/действие капчи..он отображает изображение - person Eliethesaiyan; 17.09.2013

Короткий ответ

Установите для CaptchaAction в CaptchaValidator то же значение, что и в виджете.

Длинный ответ

У меня была та же проблема: капча работала на странице контактов, но на другой странице контроллера/действия у меня не было изображения. Изменение captchaAction в виджете на «site/captcha» привело к появлению изображения, но проверка не сработала!

После нескольких исследований я обнаружил, что:

  • не устанавливая captchaAction для виджета, вызов CCaptchaAction::renderImageImagick() или CCaptchaAction::renderImageGD() создает недопустимый файл PNG (не знаю, почему)
  • согласно URL-адрес Yii CAPTCHA не работает и https://github.com/yiisoft/yii2/issues/693 Мне также нужно было добавить captchaAction в CCaptchaValidator к тому же значению в виджете CCaptcha

Теперь мой CFormModel::rules() возвращает массив с этим элементом:

array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements(), 'message'=>'Código incorreto.', 'captchaAction'=>'site/captcha'),

Надеюсь, это поможет кому-то.

person Evandro P. Alves    schedule 05.02.2014

Нужно написать еще и потому, что при перезаписи accessRules() нужно сделать действие капчи доступным для всех, вот так:

class MyController extends Controller
{
    public function accessRules() {
        return array('allow', 'actions' => array('captcha'), 'users' => array('*'));
    }
}

А также

array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements()),

Пожалуйста, найдите лучшую помощь в этих учебниках -

Добавление Captcha Yii Framework — руководство по Yii
Почему yii captcha не отображает «Получить новый код»?

person Rohit Suthar    schedule 19.06.2014