Currently I’m doing a log-in form with behaviour similar to GMail’s. That means - the CAPTCHA appears only on unsuccessful log-in.
First of all, I have tested the CAPTCHA - it works. Then I added a new variable to the CFormModel:
public $verifyCodeRequired = false;
I have changed the action to look like this:
public function actionLogin()
{
$model=new LoginForm;
// collect user input data
if(isset($_POST['LoginForm']))
{
$model->attributes=$_POST['LoginForm'];
// validate user input and redirect to the previous page if valid
if($model->validate() && $model->login())
{
$this->redirect(Yii::app()->user->returnUrl);
}
[b]$model->verifyCodeRequired = true;[/b]
}
// display the login form
$this->render('login', array('model'=>$model));
}
Using sessions is a right solution, because you need to store a value somewhere which indicates that a user was trying to login before. But putting this logic into a model is a wrong way. A model should be independent from sessions.
First of all, I don’t think that the scenarios WOULD BE enough for second-attempt-captcha-validation, because if I re-open the same URL - I see the form without CAPTCHA and it is not necessary to enter one. Refreshing the page works as expected - I still see CAPTCHA, but re-opening the same URL just makes an easy way to avoid the CAPTCHA. Spambots would benefit from this
Second - I can’t get it to work. Basically because I am setting the captchaRequired scenario AFTER the form is validated. So it means that the next time I create a model instance, the scenario is not named until the validation passes. I can’t think a way how to get the scenario name before errors occur (not CAPTCHA errors, because I can’t catch them this way).
So, my final solution is this:
combine scenarios with sessions. Store a scenario name of the model in session and re-name the scenario BEFORE the validation like this:
public function rules()
{
return array(
array('verifyCode', 'captcha', 'on'=>'captchaRequired'),
);
}
Now verifyCode won’t be validated while the current scenario is not “captchaRequired”.
Setting a scenario is easy:
$model = new LoginForm;
// if a user already tried to login, then set a scenario:
$model->scenario = 'captchaRequired';
[size=“2”][color=#1C2837]it’s working but on view doesn’t show validation message.[/color][/size] [color="#1C2837"][size=“2”]how to show validation message on view.[/size][/color]