yii2yii2-modelyii2-validation

Having trouble with Yii 2 validation rules for create and update


In Yii 1, a new instance of an active record model automatically had a scenario of 'insert', and an active record model retrieved from the database automatically had a scenario of 'update'. I found that very intuitive and helpful.

In Yii 2, active record models always have a scenario of 'default' unless we manually set a different scenario. I don't understand why that design decision was made, so my problem might be one of needing help understanding that.

In my experience, validation rules are naturally going to be slightly different for new records vs existing records (aka create vs update), and so I have added code to automatically set the scenario for my Yii 2 active record models to 'update' after I retrieve them from the database (done by responding to the after-find event). This makes it easier for me to have some validation rules that apply to both creates and updates, some that only apply to creates, and some that only apply to updates.

The problem I am hitting now is that any models that don't have any rules which only apply to update (aka that don't have any 'on' => 'update' rules) throw an Unknown scenario: update exception. I would have expected that they would simply apply the rules that apply to all scenarios.

Question:
Is there a simple way to get Yii 2 to accept my 'update' scenario even for models that don't have custom 'on' => 'update' rules? Or am I thinking about this wrong somehow?

I would like to avoid adding a dummy rule with an 'on' => 'update', and I am concerned that adding an empty 'update' entry to the array returned by scenarios() will result in none of the validation rules being applied.

I have read through this Yii 2 issue and it sounds like someone else hitting a problem much like the one I am hitting. While it did explain the reasoning for throwing an exception for unknown scenarios, it still seems more intuitive to apply the rules that would apply to that scenario (e.g. all of those without a custom on list that excludes the unknown scenario and without an except list that specifies the unknown scenario).

As a side note, to avoid having to manually set the scenario for new active record models too, we are using a CREATE constant with a value of 'default', so that new active record models automatically have a scenario that matches our CREATE constant.


Solution

  • You can overwrite scenarios() in your base AR class to always include update scenario with default scenario rules:

    public function scenarios() {
        $scenarios = parent::scenarios();
        if (!isset($scenarios['update'])) {
            $scenarios['update'] = $scenarios[self::SCENARIO_DEFAULT];
        }
    
        return $scenarios;
    }