Quiero forzar a mi sitio a actualizar la imagen captcha cada vez que se carga, por lo que tengo un método javascript activado con el evento onload (). Aquí tengo la siguiente línea:

document.getElementById('yw0_button').click;

Firebug no detecta ningún error, y para fines de prueba he agregado una alerta justo después de la línea que se muestra, y la alerta aparece cada vez que se carga la página. Sin embargo, la imagen no se actualiza.

Esto es lo que creo que es relevante sobre el archivo de vista:

<?php if(extension_loaded('gd')): ?>
    <div class="row">
        <?php echo $form->labelEx($model,'verifyCode'); ?>
        <div>
            <?php
            $this->widget('CCaptcha',
                          array('showRefreshButton'=>true,
                                'buttonType'=>'button',
                                'buttonOptions'=>
                                                    array('type'=>'image',
                                                          'src'=>"/path/images/refresh-icon.png",
                                                          'width'=>30,
                                                    ),                                                            
                                'buttonLabel'=>'Refrescar imagen'),
                          false); 
            ?>
            <br>
            <?php echo $form->textField($model,'verifyCode'); ?>
        </div>
    <div class="hint">
        Porfavor ingrese las letras como las ve en la imagen superior.
        <br/>No hay distincion entre minúsculas y mayúsculas.</div>
    </div>
<?php endif; ?>

¿Alguna idea?


@k to the z ¡acabo de ver esto! Sí, claro, si pudieras ayudarme a encontrar una solución más adecuada, ¡sería increíble! Esto es lo que creo que es relevante sobre el archivo de vista:

<?php if(extension_loaded('gd')): ?>
        <div class="row">
            <?php echo $form->labelEx($model,'verifyCode'); ?>
            <div>
                <?php
                $this->widget('CCaptcha',
                              array('showRefreshButton'=>true,
                                    'buttonType'=>'button',
                                    'buttonOptions'=>
                                                        array('type'=>'image',
                                                              'src'=>"/path/images/refresh-icon.png",
                                                              'width'=>30,
                                                        ),                                                            
                                    'buttonLabel'=>'Refrescar imagen'),
                              false); 
                ?>
                <br>
                <?php echo $form->textField($model,'verifyCode'); ?>
            </div>
        <div class="hint">
            Porfavor ingrese las letras como las ve en la imagen superior.
            <br/>No hay distincion entre minúsculas y mayúsculas.</div>
        </div>
    <?php endif; ?>

En el controlador, otorgo permiso a los usuarios autorizados en el método accessRules () para la acción captcha, y eso es todo. ¿Hay algo más que pueda publicar?

6
Soph 29 may. 2011 a las 19:06

8 respuestas

La mejor respuesta

En caso de que alguien tenga un problema similar al comenzar con Yii .. Así es como resolví el problema de CAPTCHA al activar un clic: Tengo un evento que activó el evento de carga, que tiene el siguiente código:

$ ('# yw0_button'). click ();

Seguramente debe haber una mejor manera, ¡estoy abierto a sugerencias! Sin embargo, como solución temporal, esto funciona bien, actualizando la imagen captcha cada vez que se carga la página. ¡Buena suerte!

EDITAR: lo que hice fue manejar el evento de carga de mi página html como este

<body onload="initialize()"> 
.. 
</body> 

Luego en mi archivo js:

function initialize() 
{ 
     $('#yw0_button').click(); 
} 
6
Soph 27 oct. 2011 a las 22:18

Aquí hay otra forma (¿correcta?) De hacerlo (debate):

Yii::app()->getController()->createAction('captcha')->getVerifyCode(true);
1
Ben 24 jun. 2014 a las 17:08

Agregue este javascript:

jQuery(document).ready(function() {
    jQuery.ajax({
        'success':function(html){jQuery("#yw0").attr("src",html)},
        'url':'/checkout/finish/captcha?refresh=1',
        'cache':false
    });
    return false;
});
1
bool.dev 2 ene. 2013 a las 01:06

He usado: http://www.yiiframework.com/extension/captcha-extended/

Y cambie CaptchaExtendedAction.php (ruta: extensiones / captchaExtended)

En la línea 154

$this->renderImage($this->getVerifyCode());  

Para

$this->renderImage($this->getVerifyCode(true));
1
Kevin Guan 11 ene. 2016 a las 09:09

Tengo una mejor solución para ustedes:

public function beforeAction($action)
{
    if($action->id == 'captcha'){
        $action->getVerifyCode(true);
    }
    return parent::beforeAction($action); 
}

¡Coloque estos códigos en el controlador que incluye la acción captcha!

0
ThinkAlone 15 jul. 2016 a las 08:59

Me gustaría agregar algo a la respuesta de Ezze:

Para que clientValidation funcione, puede usar la validación de captcha personalizada:

class CaptchaValidatorRefresh extends CCaptchaValidator
{
    public function clientValidateAttribute($object,$attribute)
{
    $js="";

    if(!$this->allowEmpty)
    {
        $message=$this->message!==null ? $this->message : Yii::t('yii','The verification code is incorrect.');

        $js="
            if($.trim(value)=='') {
                messages.push(".CJSON::encode($message).");
            }
        ";
    }       
    return $js;
    }
}

Y entonces

public function rules()
{
    return array(
        array('verifyCode', 'CaptchaValidatorRefresh', 'on'=>'request', 'allowEmpty'=>!CCaptcha::checkRequirements()),                          
    );
}
1
Garrett Hyde 26 oct. 2012 a las 01:06

Puede escribir el script antes del formulario beginWedget.

en cada carga de página genera el nuevo código captcha.

  $script=' $(document).ready(function() {

            document.getElementById("yw0_button").click();
    });';
  Yii::app()->clientScript->registerScript('yw0_button', $script);

  $form=$this->beginWidget('CActiveForm', array(
    'id'=>'test-form',
    'action'=>Yii::app()->createUrl('controllerName/actionName'),
    'enableClientValidation'=>true, 
    'clientOptions'=>array(
        'validateOnSubmit'=>true,
    ),
  ));

Es trabajo para mí.

Espero que también funcione para ti

1
Kailas 20 dic. 2013 a las 12:08

Espero poder proponer una mejor manera de resolver el problema mencionado por Soph . Sé que esta no es una solución relacionada con JavaScript a la que esta pregunta es adicta, pero como puedo ver, esta es la forma más correcta de hacerlo.

Me enfrenté al mismo requisito: actualizar el título en la actualización de la página pero conservar este cuando la entrada del usuario no es válida en otros campos porque repetir un nuevo código de verificación en cada falla de validación es molesto. Por lo tanto, esta tarea parece no actualizar el título en la solicitud POST y, de lo contrario, actualizarlo (solicitud GET). Una solución propuesta por Soph por sí mismo no puede lograr esto, como se podría saber, las solicitudes POST se envían al servidor y sus datos no pueden ser analizados por JavaScript del lado del cliente.

Por lo tanto, decidí mirar la implementación de captcha de Yii. Consiste en dos clases ubicadas en el paquete system.web.widgets.captcha. El primero es CCaptcha extendido desde CWidget y que usamos desde nuestro punto de vista para agregar un captcha al formulario web de la siguiente manera:

<?php 
    $this->widget("CCaptcha", array(
    'buttonLabel' => "Generate another code",
    'showRefreshButton' => false,
    'clickableImage' => true
));
?>

El último es CCaptchaAction que hace el trabajo más significativo para proporcionar un captcha generando un código de verificación y creando una imagen. Teniendo en cuenta que Yii está diseñado para estar orientado a objetos, podemos crear un par de nuestras propias clases Captcha y CaptchaAction extendidas desde CCaptcha y CCaptchaAction relativamente y colocarlas en Subdirectorio components del directorio de nuestra aplicación web.

Mi implementación de ambas clases está a continuación.

El método run() de CCaptchaAction se anula y es bastante similar al original, excepto que hay un if adicional: la ejecución de la rama cuando se establece el parámetro GET render_refreshed y donde se establece una nueva verificación el código se genera sobre la marcha y la nueva imagen correspondiente se representa y se devuelve como resultado de la acción.

Se ha introducido una variable pública refresh en la clase Captcha y su valor predeterminado es false, lo que significa que el comportamiento del widget es similar al de CCaptcha. Al anular el método renderImage, modificamos un código responsable de preparar el código HTML de salida del widget. Para ser más precisos, es donde se prepara un enlace a la acción captcha utilizado como atributo src de una etiqueta img. En el caso de refresh el miembro se establece en true, se agrega un parámetro adicional render_refreshed a este enlace.

Aquí está CaptchaAction.php:

<?php

Yii::import("system.web.widgets.captcha.CCaptchaAction");

class CaptchaAction extends CCaptchaAction
{
    const RENDER_REFRESHED_GET_VAR = "render_refreshed";

    public function run()
    {
        if (isset($_GET[self::REFRESH_GET_VAR]))  // AJAX request for regenerating code
        {
            $code = $this->getVerifyCode(true);
            echo CJSON::encode(array(
                'hash1' => $this->generateValidationHash($code),
                'hash2' => $this->generateValidationHash(strtolower($code)),
                // we add a random 'v' parameter so that FireFox can refresh the image
                // when src attribute of image tag is changed
                'url'=> $this->getController()->createUrl($this->getId(), array(
                    'v' => uniqid()
                )),
            ));
        }
        else if (isset($_GET[self::RENDER_REFRESHED_GET_VAR]))
        {
            $this->renderImage($this->getVerifyCode(true));
        }
        else
            $this->renderImage($this->getVerifyCode());
        Yii::app()->end();
    }
}

Y esto es Captcha.php:

<?php

Yii::import("web.system.widgets.CCaptcha");

class Captcha extends CCaptcha
{
    public $refresh = false;

    protected function renderImage()
    {
        if (!isset($this->imageOptions['id']))
            $this->imageOptions['id'] = $this->getId();

        if ($this->refresh)
        {
            $url = $this->getController()->createUrl($this->captchaAction, array(
                'v' => uniqid(),
                CaptchaAction::RENDER_REFRESHED_GET_VAR => 1
            ));
        }
        else
        {
            $url = $this->getController()->createUrl($this->captchaAction, array(
                'v' => uniqid()
            ));
        }
        $alt = isset($this->imageOptions['alt']) ? $this->imageOptions['alt'] : '';
        echo CHtml::image($url, $alt, $this->imageOptions);
    }
}

Entonces el uso es bastante simple. En acción, preparando los datos del modelo para la página del sitio, haga lo siguiente:

...

// Creating order model's instance
$model = new MyModel();
$refreshCaptcha = true;

if (isset($_POST['MyModel']))
{
    $refreshCaptcha = false;
    ...
}

...

$this->render("myView", array(
    'model' => $model,
    'refreshCaptcha' => $refreshCaptcha
));

Después de eso, modifique la llamada del widget de captcha en la plantilla myView de la acción de esta página:

<?php 
    $this->widget("Captcha", array(
    'buttonLabel' => "Generate another code",
    'showRefreshButton' => false,
    'clickableImage' => true,
    'refresh' => $refreshCaptcha
));

Y no olvide modificar el método actions del controlador de la página reemplazando la clase CCaptchaAction por CaptchaAction:

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

Me parece que funciona como se esperaba. Espero que esto ayude a alguien.

5
ezze 24 may. 2012 a las 23:57