Custom Validator Rule For 2 Attributes

Hi,

I have a Model Foo, with 2 attributes "bar" and "baz":

Foo->bar,

Foo->baz

"bar" and "baz" are related (they depend on eachother)

and need to be validated together

When Foo is validated (Foo->validate()) i want to be able to check dependencies between the "bar" and the "baz"

What is the best way to do that?

Is there a way that instead of passing the rules only comma separated ("bar, baz, asd"),

I could pass it a relation? ("bar + baz, asd")?

Could not find it in the docs…

Hope the question is clear

May you can use the afterValidate or beforeValidate function on AR model class like this

protected public function beforeValidate() {

if(parent::beforeValidate()) {


  // something happens here, write your code


}


 //or write your code here

}

protected function afterValidate()

{

parent::afterValidate();

if (…) $this->(attribute) = $this->(attribute2);

}

It depends what you want to do

Thanks, didn’t know there is an after validate…

but i solved it like that (int the rules function):

array(‘bar’, ‘the_rule’, ‘params’ => array(‘baz’ => $this->baz))

and created the custom-validator for ‘the_rule’

Yes, it is more easy to do like that, but if you need more complicated conditions you can ovverride above methods :)

ok thanks

Dear Friends

Let us have a real life situation.

We have a form where user has to enter his name.Then there is a boolean field(radio button) for his/her married status.

If he chooses the married status as true, then one has to enter his or her spouse name.

Otherwise errors will be thrown.

If he or she enters his spouseName without choosing the marital status,

then marital status would be assumed true.

MODEL




<?php

class TestForm extends CFormModel

{


public $name;

public $married;

public $spouseName;


public function rules()

	{

		return array(

			

			array('name', 'required'),

			array('married', 'boolean'),

			array('spouseName', 'safe'), //this is very important.

		);

	}

	

	

	public function beforeValidate()

    {

        if ($this->married) {


            $this->getValidatorList()->add(CValidator::createValidator('required',$this,'spouseName',array()));

        }

         if (!$this->spouseName==null) {


            $this->married=true; 

        }

        return  parent::beforeValidate();

    }

}


?>




view




<div class="form">


<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'test-form',

	'enableAjaxValidation'=>false,

)); ?>


	<p class="note">Fields with <span class="required">*</span> are required.</p>


	<?php echo $form->errorSummary($model); ?>


	<div class="row">

		<?php echo $form->labelEx($model,'name'); ?>

		<?php echo $form->textField($model,'name',array('size'=>60,'maxlength'=>64)); ?>

		<?php echo $form->error($model,'name'); ?>

	</div>

	<div class="row rememberMe">

		<?php echo $form->checkBox($model,'married'); ?>

		<?php echo $form->label($model,'married'); ?>

		<?php echo $form->error($model,'married'); ?>

	</div>

	<div class="row">

		<?php echo $form->labelEx($model,'spouseName'); ?>

		<?php echo $form->textField($model,'spouseName',array('size'=>60,'maxlength'=>64)); ?>

		<?php echo $form->error($model,'spouseName'); ?>

	</div>


	<div class="row buttons">

		<?php echo CHtml::submitButton('submit'); ?>

	</div>


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


</div><!-- form -->



Controller




public function actionValidate(){

	$model=new TestForm;

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

	   {

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

		   

		   $model->validate();

		   }

	

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

	}



NOTE: We has to make the rule safe for dependent attribute.Othewise we can not get the value

during massive assignment.

Regards.

Thank you, but that is not the case for me, I don’t need to assume anything is only one is selected - in my case they are correlated.

You can also do this without explicit passing of $this->baz to the custom validation method. In that custom validation method, you simply ‘refer’ to $this->baz and conditionally do any thing you want based on its status/content…