Models are part of MVC structure. They represent the rules and logic for an application. Means they hold data and define the validating rules for the data.

Model classes are extended by yii\base\Model or its child classes.

Mainly following features are implemented using models.

  • attribute declaration
  • attribute labels
  • massive attribute assignment
  • scenario-based validation
  • can not embed HTML
  • can not be directly accessed

Attributes

Attributes mainly represent the business data. Each attribute is a publicly accessible property of a model. They can be accessed like array elements or normal object properties. it is like publicly accessible properties of a model.

The method,

  1. yii\base\Model::attributes()   

specifies what attributes a model class has.

Model class is also the base class for ActiveRecord class (which is an advanced model with additional functionality).

Attribute as a normal object property:

  1. $model = new \app\models\ContactForm;  
  2.   
  3. // "name" is an attribute of ContactForm  
  4. $model->name = 'example';  
  5. echo $model->name;  
  6.   
  7. Attribute as array elements:  
  8.   
  9. $model = new \app\models\ContactForm;  
  10.   
  11. // accessing attributes like array elements  
  12. $model['name'] = 'example';  
  13. echo $model['name'];  
  14.   
  15. // Model is traversable using foreach.  
  16. foreach ($model as $name => $value) {  
  17.     echo "$name: $value\n";  
  18. }  

In earlier versions of Yii, scenarios and validation were handled with the same function. But in Yii2, they are split into different functions i.e; rules() and scenarios().

Here, rules() specify the validation of a data while scenarios() specify which attributes are safe to be assigned to the model.


Attribute Labels

Attribute labels are values which are displayed with attributes to get the input from the users.

For example, in the below code, ID, Name, Designation, Contact and Email denotes the attribute labels. All this is defined under a function attributeLabels().

  1. public function attributeLabels()   
  2.     {   
  3.         return [   
  4.             'id' => 'ID',   
  5.             'name' => 'Name',   
  6.             'designation' => 'Designation',   
  7.             'contact' => 'Contact',   
  8.             'email' => 'Email',   
  9.         ];   
  10.     }  
YII Models 1

Look at the above snapshot, the heading data denotes the attribute labels.

Scenarios

A model may be used for different scenarios. For example, a model may be used to collect login user inputs while it may also be used to collect inputs of new users for registration. So in different scenarios a model may use different rules and logic.

Example

This is the ContactForm.php code,

  1. <?php   
  2.    namespace frontend\models;   
  3.    use Yii;   
  4.    use yii\base\Model;   
  5.    /**  
  6.    * ContactForm is the model behind the contact form.  
  7.    */   
  8.    class ContactForm extends Model {   
  9.       public $name;   
  10.       public $email;   
  11.       public $subject;   
  12.       public $body;   
  13.       public $verifyCode;   
  14.        const SCENARIO_EMAIL_FROM_GUEST = 'EMAIL_FROM_GUEST';   
  15.       const SCENARIO_EMAIL_FROM_USER = 'EMAIL_FROM_USER';   
  16.        
  17.       public function scenarios() {   
  18.          return [   
  19.             self::SCENARIO_EMAIL_FROM_GUEST => ['name''email''subject',   
  20.                'body''verifyCode'],   
  21.             self::SCENARIO_EMAIL_FROM_USER => ['name''email' ,'subject''body',   
  22.                'verifyCode'],   
  23.          ];   
  24.       }   
  25.       /**  
  26.       * @return array the validation rules.  
  27.       */   
  28.       public function rules() {   
  29.          return [   
  30.             // name, email, subject and body are required   
  31.             [['name''email''subject''body'], 'required'],   
  32.             // email has to be a valid email address   
  33.             ['email''email'],   
  34.             // verifyCode needs to be entered correctly   
  35.             ['verifyCode''captcha'],   
  36.          ];   
  37.       }   
  38.       /**  
  39.       * @return array customized attribute labels  
  40.       */   
  41.       public function attributeLabels() {   
  42.          return [   
  43.            'name' => 'Name',   
  44.             'email' => 'Email',   
  45.             'subject' => 'Subject',   
  46.             'body' => 'Body',   
  47.             'verifyCode' => 'Verification Code',   
  48.          ];   
  49.       }   
  50.       /**  
  51.       * Sends an email to the specified email address using the information  
  52.          collected by this model.  
  53.       * @param  string  $email the target email address  
  54.       * @return boolean whether the model passes validation  
  55.       */   
  56.       public function contact($email) {   
  57.          if ($this -> validate()) {   
  58.             Yii::$app->mailer->compose()   
  59.                ->setTo($email)   
  60.                ->setFrom([$this->email => $this->name])   
  61.                ->setSubject($this->subject)   
  62.                ->setTextBody($this->body)   
  63.                ->send();   
  64.             return true;   
  65.          }   
  66.          return false;   
  67.       }   
  68.    }   
  69. ?>  

Create an action actionContact in SiteController.php file

  1. public function actionContact() {   
  2.  $model = new ContactForm();   
  3.  $model->scenario = ContactForm::SCENARIO_EMAIL_FROM_GUEST;   
  4.  if ($model->load(Yii::$app->request->post()) && $model->   
  5.     contact(Yii::$app->params ['adminEmail'])) {   
  6.        Yii::$app->session->setFlash('contactFormSubmitted');    
  7.        return $this->refresh();   
  8.  }   
  9.  return $this->render('contact', [   
  10.     'model' => $model,   
  11.  ]);   

Now, we'll run the program in the browser,

YII Models 2

Now change the scenarion in actionContact in SiteController.php as

  1. $model->scenario = ContactForm::SCENARIO_EMAIL_FROM_USER;  

Now on running the program in the browser, Subject and Body field will be no longer required field.

YII Models 3

Validation Rules

These are the rules which are set for the fields to be fulfilled by the users. For example, required rule will make sure that the respective field is not empty. And email attribute will make sure that the email entered is a valid email. If values do not satisfy the rules, an error message will appear on the screen.

To declare validation rules for all the fields in all the scenarios, following code is used.

  1. public function rules()  
  2. {  
  3.     return [  
  4.         // the name, email, subject and body attributes are required  
  5.         [['name''email''subject''body'], 'required'],  
  6.   
  7.         // the email attribute should be a valid email address  
  8.         ['email''email'],  
  9.     ];  
  10. }  
  11.   
  12. To declare different validation rules for different scenarios, use the following code.  
  13.   
  14. public function rules()  
  15. {  
  16.     return [  
  17.         // username, email and password are all required in "register" scenario  
  18.         [['username''email''password''d_o_b'], 'required''on' => self::SCENARIO_REGISTER],  
  19.   
  20.         // username and password are required in "login" scenario  
  21.         [['username''password'], 'required''on' => self::SCENARIO_LOGIN],  
  22.     ];  
  23. }  

The on property implements that, rule will be applied to a particular scenario. If you'll not use on property than by default rule will be applied for all the fields.


Massive Assignment

In massive assignment, a model is populated with user inputs using a single line of code. Massive assignment only applies to the safe attributes.

Look at the following two types of code, both assigning the submitted form data by the end users to attributes of the ContactForm model.

First one is,

  1. $model = new \app\models\ContactForm;  
  2. $model->attributes = \Yii::$app->request->post('ContactForm');  
  3. Second one is,  
  4.   
  5.   
  6. $model = new \app\models\ContactForm;  
  7. $data = \Yii::$app->request->post('ContactForm', []);  
  8. $model->name = isset($data['name']) ? $data['name'] : null;  
  9. $model->email = isset($data['email']) ? $data['email'] : null;  
  10. $model->subject = isset($data['subject']) ? $data['subject'] : null;  
  11. $model->body = isset($data['body']) ? $data['body'] : null;  

The first one using massive assignment is much easier, neat and less error prone.