Valery Bulash
Valery Bulash

Reputation: 413

Yii2 - dynamically switch rules set in model

I want to dynamically substitute rules in model according to switch value on form.

In view:

<?php
    $form = ActiveForm::begin([
        'enableAjaxValidation' => true,
        'validationUrl' => Url::toRoute('anounce/validation')
    ]);
?>

In controller:

public function actionValidation()
{
    $model = new Anounce();
    if (Yii::$app->request->isAjax && $model->load(Yii::$app->
        request->post())) {
        Yii::$app->response->format = 'json';
        return ActiveForm::validate($model);
    }
}

Excerpts from model:

class Anounce extends \yii\db\ActiveRecord
{
    private $currentRuleSet;    // Current validation set
    // Here are arrays of rules with assignment
    private $fullRuleSet;  // = [...];
    private $shortRuleSet; // = [...];
    private $minRuleSet;   // = [...];

    public function init()
    {
        parent::init();
        $this->currentRuleSet = $this->fullRuleSet;
    }

    public function rules()
    {
        return $this->currentRuleSet;
    }

    public function beforeValidate()
    {
        if ($this->idanounce_type === self::FULL) {
            $this->currentRuleSet = $this->fullRuleSet;
        } else if ($this->idanounce_type === self::SHORTER) {
            $this->currentRuleSet = $this->shortRuleSet;
        } else if ($this->idanounce_type === self::MINIMAL) {
            $this->currentRuleSet = $this->minRuleSet;
        }
        return parent::beforeValidate();
    }
}

Variable idanounce_type is a switch between rules. Unfortunately, validation made according to full rules set (or rules set used in init), despite on which *RuleSet value assigned to currentRuleSet.

How to write dynamic switching of rules?

Upvotes: 0

Views: 1500

Answers (1)

mrateb
mrateb

Reputation: 2499

What you want here is to change validation according to the user's input. You can do this by defining scenarios in your model.

So firstly set scenarios where you put in it the fields that are to be validated. Example if you have username, password, and email fields, and you defined two scenarios, in SCENARIO_FIRST only username and password will get validated.

public function scenarios()
{
    return [
        self::SCENARIO_FIRST => ['username', 'password'],
        self::SCENARIO_SECOND => ['username', 'email', 'password'],
    ];
}

Then in your controller, set the scenario according to the input:

public function actionValidation()
{
    $model = new Anounce();

    //example
    if($condition == true) 
    {
       $model->scenario = Anounce::SCENARIO_FIRST;
    }

    if (Yii::$app->request->isAjax && $model->load(Yii::$app->
        request->post())) {
        Yii::$app->response->format = 'json';
        return ActiveForm::validate($model);
    }
}

Read more about scenarios here and how to use them with validation here:

http://www.yiiframework.com/doc-2.0/guide-structure-models.html#scenarios

Upvotes: 2

Related Questions