3

I have MyEntity.php model. As a part of the model script, there are some rules and some scenarios defined:

public function rules()
{
    return [
        [['myentity_id', 'myentity_title', 'myentity_content', 'myentity_date'], 'required'],
        [['myentity_id'], 'integer'],
        [['myentity_title', 'myentity_content'], 'string', 'max' => 120],
        [['myentity_date'], 'safe'],            
    ];
}

public function scenarios()
{
    $scenarios = parent::scenarios();
    $scenarios['scenario_one'] = ['myentity_id', 'myentity_title'];
    $scenarios['scenario_two'] = ['myentity_id', 'myentity_content'];
    return $scenarios;
}

I need to be able to have different scenarios, and for different actions only certain validations (by params) to be active. For example, scenario_one for actionOne, scenario_two for actionTwo etc.

Here is some small part of code from the controller:

public function actionOne($id)
{           
    $modelMyEntity = $this->findModel($id);
    $modelMyEntity->scenario = 'scenario_one';
    .
    .
    .
}

public function actionTwo($id)
{           
    $modelMyEntity = $this->findModel($id);
    $modelMyEntity->scenario = 'scenario_two';
    .
    .
    .
}

Now I want to have a scenario_three where there should NOT be any validations at all. I'll have additional checks in code that will prevent failing while storing in database. I'll just need to make sure that no validations are applied because it's preventing my form from submitting. If I don't apply any scenario, then the default scenario is applied (all listed validations will be active, which is totally opposite of the scenario I need).

delux
  • 1,694
  • 10
  • 33
  • 64

2 Answers2

4

If I correctly understood your question, you can assign scenario_three as current scenario: model will not find matched rules and will skip validation checks.

public function actionThree($id)
{           
    $modelMyEntity = $this->findModel($id);
    $modelMyEntity->scenario = 'scenario_three';
    .
    .
    .
}

UPD: However I strictly recommend to define explicitly all scenarios and corresponding active attributes (in scenario method) and remove $scenarios = parent::scenarios();, because it can cause unnecessary effects. Parent implementation is mostly developed to backward compatibility with Yii1, that has no scenarios() methods. And it is assumed usually if you override scenarios() method, you should not merge your explicitly defined scenarios with parent implementation.

IStranger
  • 1,868
  • 15
  • 23
  • I like this too, it's quite simple and easy to understand. :) Here's an upvote for you. – Gynteniuxas Sep 25 '16 at 18:21
  • @EdvinTenovimas Thanks) – IStranger Sep 25 '16 at 18:52
  • @IStranger, can you please also post a piece of code, how this description should look like in practice (what changes should be applied in the "rules()" and "scenarios()" functions, from my original question)? – delux Oct 07 '16 at 13:53
4

To be able to do this, you need to do a few things (including the ones you almost did yourself):

  • In your controller, write $modelMyEntity->scenario = 'scenario_three';

  • In model, add an additional scenario array 'scenario_three' in scenarios() method:

Like this:

$scenarios['scenario_three'] = ['myentity_id', 'myentity_content'];
  • Finally, most changes will be required in rules() as you will need to add where to include or exclude specific scenarios.

Basically, in each rule you can now write except conditional and point which attributes will not comply to which scenario. So in your example, let's say, let's exclude all attributes for scenario_three:

[['myentity_id', 'myentity_title', 'myentity_content', 'myentity_date'], 'required', 'except' => 'scenario_three'],
[['myentity_id'], 'integer', 'except' => 'scenario_three'],
[['myentity_title', 'myentity_content'], 'string', 'max' => 120, 'except' => 'scenario_three'],
[['myentity_date'], 'safe'],

This is a little different solution to how to ignore rules but I find this more attractive because in future it would be easier to add/remove specific attributes for this scenario and will also be easier for other developers (if there are more than just you) to understand what you're trying to do.

But I think @iStranger's solution works too (much simpler).

Gynteniuxas
  • 7,035
  • 18
  • 38
  • 54
  • 2
    I like the usage of except conditional – Kiran Muralee Sep 25 '16 at 18:24
  • @KiranMuralee Thanks for the support! I hope others will find this useful. – Gynteniuxas Sep 25 '16 at 18:25
  • This solution is a little better because a case like this jQuery will still show validation (green fields, though) if you do some more changes with jQuery. –  Sep 25 '16 at 18:32
  • @Edvin Tenovimas Is this information in Yii2 guide.I searched for it but couldnt find.However I find the usage of 'on'.eg // username, email and password are all required in "register" scenario [['username', 'email', 'password'], 'required', 'on' => self::SCENARIO_REGISTER], – Kiran Muralee Sep 25 '16 at 18:32
  • @KiranMuralee I can provide very detailed information about these scenarios, if you want to. But it's better to use either email or something similar because explanation would take more space than comments allow symbols. :) In short, I believe there should be at least one example with `except`, but not sure, didn't check. – Gynteniuxas Sep 25 '16 at 18:34
  • @EdvinTenovimas Ok.Let me try this practically.If it works its really useful,thanks for the info :) – Kiran Muralee Sep 25 '16 at 18:37
  • @KiranMuralee If you need more help, you can write either create a new question or write me an email. :) I should notice in both cases. – Gynteniuxas Sep 25 '16 at 18:41
  • `except` is typical feature in Yii1. Of course it will work. However in my opinion it not convenient when you have more than 5 scenarios and 20 attributes. In this case `rules` method will not readable. Yii2 allows to split managing "active"/"safe" attributes (via `scenarios` method) and validation rules (via `rules` method). I think, it causes less confusion in the code. – IStranger Sep 25 '16 at 19:04
  • @IStranger Well, that depends on how programmers are used to. For me personally, I prefer describe all scenarios in model, regardless of how many attributes are using. – Gynteniuxas Sep 25 '16 at 19:07
  • @EdvinTenovimas Of course, that is why Yii2 was left the implementation of Yii1: the part of the programmers consider this approach more convenient :) – IStranger Sep 25 '16 at 19:24
  • @IStranger Well, I have never used Yii1, just I saw that I prefer this way since it's a little easier for me. I see we could talk a lot about Yii2. I should remember that in case I need some help in future. – Gynteniuxas Sep 25 '16 at 19:34
  • @EdvinTenovimas I'm confused by the fact the: In the rules you are defining for attributes that they should not be included in the scenario with "except" word. From the other side, when defining the scenario in "scenarios" method, you are listing two attributes there. So do we need to list them there? Should the scenario be defined there (in scenarios method) there at all? – delux Oct 02 '16 at 18:19
  • @delux If you're excluding these attributes from `scenario_three` scenario (and from `rules()`), input values with such attributes will be ignored by system (user input will have no meaning). In your case, you can remove attributes from `scenario_three`, but then they will have all the rules that are applied to other scenarios (if there any) or you might get something like undefined scenario (*It's evening so it's hard to think and explain, I can do that tomorrow*). :) – Gynteniuxas Oct 02 '16 at 18:57
  • @EdvinTenovimas please take some time and consider my question from the comment (whenever you can). I'm still confused with the fact from my last comment. – delux Oct 06 '16 at 10:29
  • @delux To put this simply, in your case IStranger's solution might work too. Only my case works when you're going to add more attributes (you want to validate) in future. – Gynteniuxas Oct 06 '16 at 16:06