3

I write two scenario in Yii2 comment model, when user logged on or is guest.

my rules is:

public function rules()
    {
        return [
            [['user_id'], 'required', 'on' => self::SCENARIO_USER],
            [['name', 'email'], 'required', 'on' => self::SCENARIO_GUEST],
            [['post_id', 'body', 'date'], 'required'],
            [['user_id', 'parent_id', 'post_id', 'status'], 'integer'],
            [['body'], 'string'],
            [['date'], 'safe'],
            [['name', 'email', 'site'], 'string', 'max' => 256],
        ];
    }

and senarios funtion :

public function scenarios()
{
    $scenarios = parent::scenarios();
    $scenarios[self::SCENARIO_GUEST] = ['name' , 'email'];
    $scenarios[self::SCENARIO_USER] = ['user_id'];
    return $scenarios;
}

I use it as follows:

$commentModel = Yii::$app->user->isGuest ? new Comment(['scenario' => Comment::SCENARIO_GUEST]) : new Comment(['scenario' => Comment::SCENARIO_USER]);

if guest view form, only name and email checked and user fill form, no field checked ! why other rules don't check? how to fix it?

Masoud92m
  • 542
  • 6
  • 20

2 Answers2

4

Refer Yii2 Scenarios

The scenarios() method returns an array whose keys are the scenario names and values the corresponding active attributes. An active attribute can be massively assigned and is subject to validation.

public function scenarios()
{
     $scenarios = parent::scenarios();
     $scenarios[self::SCENARIO_GUEST] = ['name' , 'email', 'date', 'body', 'site', 'post_id'];
     $scenarios[self::SCENARIO_USER] = ['user_id', 'date', 'body', 'site', 'post_id'];
     return $scenarios;
}
vishuB
  • 3,840
  • 5
  • 26
  • 46
  • An additional tip, if you got over 5 attributes, you can get all the attributes and only remove the matching ones. Say you want to exclude an attribute in a particular scenario, instead of listing 10 attributes in order to exclude a single one, you could `array_diff(array_flip($this->attributes), ['excludedAttribute1', 'excludedAttribute2'])`, I'm on my phone, but I think you need to flip $this->attributes due to key holding attribute name and value holding attribute value, no matter if the model's attributes have been assigned a value or not. – Ravenous Jun 06 '18 at 11:25
2

If you use scenarios() you need to define all attributes allowed to assign in given scenario. So if you want to allow guest to edit also body and date you need something like:

public function scenarios()
{
    $scenarios = parent::scenarios();
    $scenarios[self::SCENARIO_GUEST] = ['name' , 'email', 'body', 'date'];
    $scenarios[self::SCENARIO_USER] = ['user_id'];
    return $scenarios;
}

If you have many "shared" attributes between scenarios, you probably should not override this method and define it in rules() only.

See more in scenarios documentation.

rob006
  • 18,710
  • 5
  • 41
  • 58