Yii - dynamically change rules from controller

11,229

Solution 1

You can use scenario. In the model:

class Model extends CActiveRecord {
    // ....
    public function rules() {
        return array(
            array('colour', 'required', 'on' => 'hasColour')
        );
    }
    // ....
}

And in the controller:

public function actionOrder() {
    // ....
    $model = new Product();
    if ($product->HasColour) {
        $model->setScenario('hasColour');
    }
}

So, required colour will be validated when the model's scenario is hasColour

Solution 2

class LoginForm extends CFormModel
{
    public $username;
    public $password;
}

$form = new LoginForm();
$form->validatorList->add(
    CValidator::createValidator('required', $form, 'username, password')
);

Now $form has two required fields.

Solution 3

One approach is to use a custom validation rule. For example, the rule:

array('colour', 'requiredOnHasColour'),

And then the validator method in the same model class:

public function requiredOnHasColour($attribute, $params) {
    if ($this->hasColour && $this->$attribute == null)
        $this->addError($attribute, 'Colour is required.');
}

More info: Create your own validation rule

Solution 4

If you want to do more complicated logic, then scenarios might not satisfy your needs. Then you can override method init and do all the logic that define validation rules over there, adding results to $validationRules array. And the in rules() method you just return that array. Something like that:

 class Person extends CActiveRecord
{
    public function init(){
        if( TRUE){
            $this->validationRules[] = array('first_name','required');
            $this->validationRules[] = array('last_name','required');
        }

    }

    public $validationRules = array(
        array('email', 'required'),
        array('email, email1, email2, email3', 'email', 'message'=>'Email format is invalid'),
        array('email, address, email1, email2, email3', 'length', 'max'=>255),

    );

    public function rules()
    {
        return $this->validationRules;
    }
}
Share:
11,229
Adrian Gunawan
Author by

Adrian Gunawan

Updated on June 12, 2022

Comments

  • Adrian Gunawan
    Adrian Gunawan almost 2 years

    Let's say I have a product which can have a colour. Depending on the product type, the colour field may or may not be required.

    If colour is always required, I would have the following in the product model

    public function rules()
    {
        return array(
            array('colour', 'required')
        );
    }
    

    However, I want this to be dynamic depending on the product type.

    Should this be done in the controller? I would imagine having something like the following in the controller:

    public function actionOrder() {
        // ....
        if ($product->HasColour) {
            // set the colour validation to be required
        } else {
            // set the colour validation to be not required
        }
    }
    

    What is the best way to approach this?

    Thanks