Note: these code is for the Yii-1.1.x, if you are using Yii-1.0.x, you should modify the part 4, pass into the secnario parameter.
This implementation seems clumsy, if you have a better way, tell me please, thanks you!
- Specify the scenario name in the action of controller.
function actionLogin()
{
...
$model = new User;
$model->setScenario('login');
...
}
- Add the validate rule for Model class
public function rules()
{
return array(
array('verifyCode', 'safe'),
array('verifyCode', 'captcha', 'allowEmpty'=>false, 'captchaAction'=>'site/captcha', 'on'=>'login2'),
...
}
- Add a public method to check whether the image verify code is required or not.
public function isReqCaptcha()
{
if ($this->getSecnario() == 'login' || $this->getSecnario() == 'login2')
{
$logCaptchaed = Yii::app()->user->getState('logCaptchaed');
if ($logCaptchaed > 2) // failed 3 times
return true;
}
return false;
}
- Overwrite the validate() and afterValidate() of the Model:
public function validate($attributes = NULL)
{
$scenario = $oldscenario = $this->getScenario();
// change the scenario to force check verify code...
if ($scenario == 'login' && $this->isReqCaptcha())
$scenario .= '2';
$this->setScenario($scenario);
$ret = parent::validate($attributes);
// resotre the scnario value
$this->setScenario($oldscenario);
return $ret;
}
protected function afterValidate()
{
if ($this->getScenario() == 'login' || $this->getSecnario() == 'login2')
{
if ($this->isReqCaptcha())
{
if (!$this->hasErrors('verifyCode')) // correct verify code, reset!
Yii::app()->user->setState('logCaptchaed', 0);
}
else
{
$logCaptchaed = Yii::app()->user->getState('logCaptchaed');
Yii::app()->user->setState('logCaptchaed', $this->hasErrors() ? ($logCaptchaed + 1) : 0);
}
}
parent::afterValidate();
}
- Add the condition code to show verify code in View file of login action:
<?php if ($model->isReqCaptcha()) { ?>
<div class="simple">
<?php echo CHtml::activeLabel($model, 'verifyCode'); ?>
<div>
<?php $this->widget('CCaptcha', array('captchaAction'=>'site/captcha')); ?><br />
<?php echo CHtml::activeTextField($model, 'verifyCode'); ?>
</div>
</div>
<?php } ?>