Validation rule not firing for a model variable

Hi, I am fairly new to yii, I am sorry if this is a dump question.

I have a “user registration” active record model with bunch of variable mirroring the db column and one variable ($forget_email) that is just on its own, that variable that’s on its own is use if someone forgets their password, the variable will store the email on POST and is then is use to send emails. The problem comes when I submit the post, I have rules so that it will check it must be an email, and require on submit, however only the email checking rule is fired. For the life of me, I could not work out what I have done wrong. Maybe this is obvious to some of you.

Here are the code for the Model:




class Registration extends CActiveRecord

{


	public $password_repeat;

	public $forget_email;


	....

public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		

		return array(

				

			array('email, firstname, lastname,  password, company, password_repeat', 'required', 'on'=>'index'),

			array('forget_email', 'required', 'on'=>'forgetpassword'),

			array('forget_email', 'length', 'min'=>2),

			array('confirm', 'numerical', 'integerOnly'=>true),

			array('email, forget_email', 'email'),

			array('firstname, lastname, password, email, forget_email, company, registrationkey', 'length', 'max'=>255),

			array('create_time, password_repeat', 'safe'),

			array('password', 'compare'),

	

			array('id, username, password, email, create_time, company, registrationkey', 'safe', 'on'=>'search'),

		

		);

		

	}




On the Controller





class RegistrationController extends Controller

{


public function actionForgetpassword()

	{

		$model = new Registration;		

		$message = '';


		if(isset($_POST['Registration']))

		{


			$model->attributes=$_POST['Registration'];

		        if($model->validate())

			{


					

					

				$message = '

					Great email sent.

					';


			}


		}

	

		$this->render('forgetpassword', array('model'=>$model, 'message'=>$message));	


	}

....		

}




The view for the page




<?php /** @var BootActiveForm $form */

$form = $this->beginWidget('bootstrap.widgets.BootActiveForm', array(

    'id'=>'passwordrecovery',

    'type'=>'horizontal',

    'enableAjaxValidation'=>true,

)); ?>

 

<h1>Forgotten your password?</h1>

<p>&nbsp;</p>

<p class="lead">To reset your password, please enter the registred email address. A link will be emailed to your address which will let you reset your password. </p>


<?php echo $message."<p>"; ?>


Enter your email address:<p></p>

<?php echo $form->textFieldRow($model, 'forget_email', array('class'=>'input-xlarge marginright', 'maxlength'=>100)); ?>

<p></p>

<?php echo CHtml::htmlButton('Send reset request', array('class'=>'btn btn-info', 'type'=>'submit')); echo " or "?>


<?php echo CHtml::link('Cancel', array('site/login'),array('class'=>'btn btn-warning'));  ?>


<?php $this->endWidget(); ?>




I am sorry this is a bit long, I have try


echo CActiveForm::validate($model);

and all I see is the email rule firing.

Thanks in advance.

Best Regards

Jason

Hi. You are specifying the forgetpassword scenario in your email required rule, but you’re not setting it in your controller.

Try this


$model = new Registration('forgetpassword');

Edit: Likewise, you specify ‘index’ scenario as well, do you use such a scenario. You could use the standard ones (insert, update…)

See also: http://www.yiiframework.com/wiki/266/understanding-scenarios/

Thanks you pal, that’s is perfect!!!! I do have just a “index” and the rule worked even without specifying $model = new Registration(‘index’); just $model = new Registration; I guess it must be defaulted to index. Wahaoo~~! that solved the puzzle.! funny thing was email and one of my customer rule worked also :mellow: thanks again mate and I will take a read the link that you kindly provided.

Sorry mate please call me stupid, further to this. I added a custom rules that checks if an email is exists in the database. (with the option for different error message)

With the forget_email set to require on forgetpassword page, somehow the rule that checks the forget_email is still firing at index. Making the submit always failed. I have tried adding the forget_email in the "safe" list, but still no luck, am I missing another doco that I should be reading? Thanks in advance.

Modal




		return array(

				

			array('email, firstname, lastname,  password, company, password_repeat', 'required', 'on'=>'index'),

			array('forget_email', 'required', 'on'=>'forgetpassword'),

			array('confirm', 'numerical', 'integerOnly'=>true),

			array('email, forget_email', 'email'),

			array('firstname, lastname, password, email,  company, registrationkey', 'length', 'max'=>255),

			array('create_time, forget_email', 'safe'),

			array('password', 'compare'),

			array('email', 'ifemailexists', 'exists'=> 'nonexists'),

                        //I expect this to only fire at "forgetpassword" view page but it's firing at index as well.

			array('forget_email', 'ifemailexists', 'exists'=> 'exists'), 

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('id, username, password, email, create_time, company, registrationkey', 'safe', 'on'=>'search'),

		

		);


public function ifemailexists($attribute,$params)

	{

	 	$targetemail =$this->$attribute;


	 	$user = new User();


	 	if($params['exists'] === 'nonexists')

	 	{

	 		if ($user->findByAttributes(array('email'=>$targetemail)))

	 			$this->addError($attribute, 'Email already exists.');		


		}

		if($params['exists'] === 'exists')

		{

	    	if(!$user->findByAttributes(array('email'=>$targetemail)))

	      		$this->addError($attribute, 'Email doesn\'t exists.');

	    }

	    	

	}




In Controller




public function actionIndex()

	{

		

		$model=new Registration('index');


		// Uncomment the following line if AJAX validation is needed

		 $this->performAjaxValidation($model);




		if(isset($_POST['Registration']))

		{

			$model->attributes=$_POST['Registration'];

			$model->create_time = new CDbExpression('NOW()');

			$model->registrationkey = $this->rand_string(12);

			//$model->forget_email = 'dummy@encoo.com.au';

			if($model->save())

			{

				$this->redirect(array('congra'));

			}else

			{

				echo CActiveForm::validate($model);

			}

				

		}


			$this->render('index',array(

				'model'=>$model, 

			));

			

	}



If you don’t specify a scenario in your rule, it’s always checked.

So you may want to do this


array('email', 'email'),

array('forget_email', 'email', 'on'=>'forgetpassword'), // this rule has to be split from the previous one

…

array('forget_email', 'ifemailexists', 'exists'=> 'exists', 'on'=>'forgetpassword'),

Likewise, you have to make sure each rule should be only validated on the needed scenario: insert, update, forgetpassword, etc.

You are a legend!!! I set the scenario first thing after reading you reply, but I had no idea you could chain the validation rules such as "on". And that was it!