Using scenarios with ActiveForm

I’m pretty new to using Yii and I have been building a form to submit and I understand you setup your validation rules such as:

My Model:




namespace app\models;


use yii\base\model;


class CompanySignupForm extends Model {

	

	public $company_name;

	public $first_name;

	public $last_name;

	public $email;

	public $username;

	public $password;

	public $password2;

	

	public function rules() {		

        return [

            [['company_name', 'first_name'], 'required'],

			[

			  'company_name', 'match', 'not' => true, 'pattern' => '/[^a-zA-Z0-9 ]/',

			  'message' => 'Company name must consist of letters, numbers and spaces only', 'on' => 'company'

			],

        ];

	}

	

}

But how do you pass the scenario?

This is the method it submits to in my controller:


public function actionCompanySignup() {

	

	$signup = new CompanySignupForm();

	

	if ($signup->load(Yii::$app->request->post()) and $signup->validate()) {

		

		if (Yii::$app->request->isAjax) {

			

			

			

		}

	

	} else {

		

		

	

	}

	

}

As I understand it you should pass the scenario such as:


$signup = new CompanySignupForm('company');

But how does that work? Will I need to add a constructor to my model to handle that or how is this done?

No, you’d set it like this:




$signup = new CompanySignupForm(['scenario'=>'company']);



or:




$signup = new CompanySignupForm();

$signup->scenario = 'company';



The default constructor will make sure that the scenario property is set if you use the first version.

See the details here.

Ok thank you!

So do I need a scenarios method as well or is that only for usage in classes that extend the ActiveRecord class?

You don’t need the scenarios method. It’s just a way to specify more directly which fields can be massively assigned on each scenario.

Ok thanks.

So, for example, I could change the name of this model to SignupForm and then call it like:


$signup = new SignupForm(['scenario'=>'company']);

or


$signup = new SignupForm(['scenario'=>'client']);

Reason being is clients and companies share data in the users table and each respectively has entries in the companies or clients tables.

Either that or you could create a SignupForm base class with the shared functionality and CompanySignupForm and ClientSignupForm extending that.

Assuming Yii 2 is the same as Yii (I’ve not delved into it much yet), you don’t need to specify a scenario.

Excellent - thanks. I just came onto Yii from Yii 2, never used version 1.

Hmmmmmmmm… just read this:

http://www.yiiframework.com/doc-2.0/guide-input-validation.html#declaring-rules

So it’s sounding like I may need a scenarios method!?

From here:

Unless you’re configuring your model so that it can handle multiple different scenarios, you don’t need to worry about the scenario at all. Specifically, your rules will be configured to apply to all scenarios, and the default implementation of scenarios() will make those attributes with rules active automatically.

Assuming that you don’t want to manage different scenarios, there’s no reason to specify scenario information anywhere in your model or action.

Alright - thanks.

If I am using multiple scenarios then would the only reason to create my own scenarios method be if I wanted to restrict the "safe" attributes?

That would be my understanding.

Just an update on this:


$signup = new SignupForm(['scenario' => 'company']);

That doesn’t work by itself. If you are going to do that, then you need something like this in your model:




function __construct($config) {

    $this->scenario = $config['scenario'];

}



…or alternatively you can do something like this:


$signup = new SignupForm();

$signup->scenario = 'company';

as stated above.