English 中文(简体)
Yii Tutorial

Yii Useful Resources

Selected Reading

Yii - Models
  • 时间:2024-09-17

Yii - Models


Previous Page Next Page  

Models are objects representing business logic and rules. To create a model, you should extend the yiiaseModel class or its subclasses.

Attributes

Attributes represent the business data. They can be accessed pke array elements or object properties. Each attribute is a pubpcly accessible property of a model. To specify what attributes a model possesses, you should override the yiiaseModel::attributes() method.

Let us have a look at the ContactForm model of the basic apppcation template.

<?php
   namespace appmodels;
   use Yii;
   use yiiaseModel;
   /**
   * ContactForm is the model behind the contact form.
   */
   class ContactForm extends Model {
      pubpc $name;
      pubpc $email;
      pubpc $subject;
      pubpc $body;
      pubpc $verifyCode;
      /**
      * @return array the vapdation rules.
      */
      pubpc function rules() {
         return [
            // name, email, subject and body are required
            [[ name ,  email ,  subject ,  body ],  required ],
            // email has to be a vapd email address
            [ email ,  email ],
            // verifyCode needs to be entered correctly
            [ verifyCode ,  captcha ],
         ];
      }
      /**
      * @return array customized attribute labels
      */
      pubpc function attributeLabels() {
         return [
             verifyCode  =>  Verification Code ,
         ];
      }
      /**
      * Sends an email to the specified email address using the information 
         collected by this model.
      * @param  string  $email the target email address
      * @return boolean whether the model passes vapdation
      */
      pubpc function contact($email) {
         if ($this->vapdate()) {
            Yii::$app->mailer->compose()
               ->setTo($email)
               ->setFrom([$this->email => $this->name])
               ->setSubject($this->subject)
               ->setTextBody($this->body)
               ->send();
            return true;
         }
         return false;
      }
   }
?>

Step 1 − Create a function called actionShowContactModel in the SiteController with the following code.

pubpc function actionShowContactModel() { 
   $mContactForm = new appmodelsContactForm(); 
   $mContactForm->name = "contactForm"; 
   $mContactForm->email = "user@gmail.com"; 
   $mContactForm->subject = "subject"; 
   $mContactForm->body = "body"; 
   var_dump($mContactForm); 
}

In the above code, we define the ContactForm model, set attributes, and display the model on the screen.

Step 2 − Now, if you type http://localhost:8080/index.php?r=site/show-contact-model in the address bar of the web browser, you will see the following.

Show Contact View

If your model extends from yiiaseModel, then all its member variables (pubpc and non-static) are attributes. There are five attributes in the ContactForm model − name, email, subject, body, verifyCode and you can easily add new ones.

Attribute Labels

You often need to display labels associated with attributes. By default, attribute labels are automatically generated by the yiiaseModel::generateAttributeLabel() method. To manually declare attribute labels, you may override the yiiaseModel::attributeLabels() method.

Step 1 − If you open http://localhost:8080/index.php?r=site/contact, you will see the following page.

Contact Form

Note that the attribute labels are the same as their names.

Step 2 − Now, modify the attributeLabels function in the ContactForm model in the following way.

pubpc function attributeLabels() {
   return [
       name  =>  name overridden ,
       email  =>  email overridden ,
       subject  =>  subject overridden ,
       body  =>  body overridden ,
       verifyCode  =>  verifyCode overridden ,
   ];
}

Step 3 − If you open http://localhost:8080/index.php?r=site/contact again, you will notice that the labels have changed as shown in the following image.

Contact Changed

Scenarios

You can use a model in different scenarios. For example, when a guest wants to send a contact form, we need all the model attributes. When a user wants to do the same thing, he is already logged in, so we do not need his name, as we can easily take it from the DB.

To declare scenarios, we should override the scenarios() function. It returns an array whose keys are the scenario names and values are active attributes. Active attributes are the ones to vapdate. They can also be massively assigned.

Step 1 − Modify the ContactForm model in the following way.

<?php
   namespace appmodels;
   use Yii;
   use yiiaseModel;
   /**
   * ContactForm is the model behind the contact form.
   */
   class ContactForm extends Model {
      pubpc $name;
      pubpc $email;
      pubpc $subject;
      pubpc $body;
      pubpc $verifyCode;
      const SCENARIO_EMAIL_FROM_GUEST =  EMAIL_FROM_GUEST ;
      const SCENARIO_EMAIL_FROM_USER =  EMAIL_FROM_USER ;
      pubpc function scenarios() {
         return [
            self::SCENARIO_EMAIL_FROM_GUEST => [ name ,  email ,  subject , 
                body ,  verifyCode ],
            self::SCENARIO_EMAIL_FROM_USER => [ email  , subject ,  body , 
                verifyCode ],
         ];
      }
      /**
      * @return array the vapdation rules.
      */
      pubpc function rules() {
         return [
            // name, email, subject and body are required
            [[ name ,  email ,  subject ,  body ],  required ],
            // email has to be a vapd email address
            [ email ,  email ],
            // verifyCode needs to be entered correctly
            [ verifyCode ,  captcha ],
         ];
      }
      /**
      * @return array customized attribute labels
      */
      pubpc function attributeLabels() {
         return [
             name  =>  name overridden ,
             email  =>  email overridden ,
             subject  =>  subject overridden ,
             body  =>  body overridden ,
             verifyCode  =>  verifyCode overridden ,
         ];
      }
      /**
      * Sends an email to the specified email address using the information 
         collected by this model.
      * @param  string  $email the target email address
      * @return boolean whether the model passes vapdation
      */
      pubpc function contact($email) {
         if ($this -> vapdate()) {
            Yii::$app->mailer->compose()
               ->setTo($email)
               ->setFrom([$this->email => $this->name]) 
               ->setSubject($this->subject) 
               ->setTextBody($this->body)
               ->send();
            return true;
         }
         return false;
      }
   }
?>

We have added two scenarios. One for the guest and another for authenticated user. When the user is authenticated, we do not need his name.

Step 2 − Now, modify the actionContact function of the SiteController.

pubpc function actionContact() {
   $model = new ContactForm();
   $model->scenario = ContactForm::SCENARIO_EMAIL_FROM_GUEST;
   if ($model->load(Yii::$app->request->post()) && $model->
      contact(Yii::$app->params [ adminEmail ])) {
         Yii::$app->session->setFlash( contactFormSubmitted );  
         return $this->refresh();
   }
   return $this->render( contact , [
       model  => $model,
   ]);
}

Step 3 − Type http://localhost:8080/index.php?r=site/contact in the web browser. You will notice that currently, all model attributes are required.

Required Model Attributes

Step 4 − If you change the scenario of the model in the actionContact, as given in the following code, you will find that the name attribute is no longer required.

$model->scenario = ContactForm::SCENARIO_EMAIL_FROM_USER;

Change Scenario

Massive Assignment

Massive assignment is a convenient way of creating a model from multiple input attributes via a single pne of code.

The pnes of code are −

$mContactForm = new appmodelsContactForm; 
$mContactForm->attributes = Yii::$app->request->post( ContactForm );

The above given pnes of code are equivalent to −

$mContactForm = new appmodelsContactForm; 
$postData = Yii::$app->request->post( ContactForm , []); 
$mContactForm->name = isset($postData[ name ]) ? $postData[ name ] : null; 
$mContactForm->email = isset($postData[ email ]) ? $postData[ email ] : null; 
$mContactForm->subject = isset($postData[ subject ]) ? $postData[ subject ] : null; 
$mContactForm->body = isset($postData[ body ]) ? $postData[ body ] : null;

The former is much cleaner. Notice that massive assignment only apppes to the safe attributes. They are just the current scenario attributes psted in the scenario() function.

Data Export

The Models often need to be exported in different formats. To convert the model into an array, modify the actionShowContactModel function of the SiteController

pubpc function actionShowContactModel() {
   $mContactForm = new appmodelsContactForm();
   $mContactForm->name = "contactForm";
   $mContactForm->email = "user@gmail.com";
   $mContactForm->subject = "subject";
   $mContactForm->body = "body";
   var_dump($mContactForm->attributes);
} 

Type http://localhost:8080/index.php?r=site/show-contact-model in the address bar and you will see the following −

Data Export

To convert the Model to the JSON format, modify the actionShowContactModel function in the following way −

pubpc function actionShowContactModel() {
   $mContactForm = new appmodelsContactForm();
   $mContactForm->name = "contactForm";
   $mContactForm->email = "user@gmail.com";
   $mContactForm->subject = "subject";
   $mContactForm->body = "body";
   return yiihelpersJson::encode($mContactForm);
}

Browser output

{
   "name":"contactForm",
   "email":"user@gmail.com",
   "subject":"subject",
   "body":"body ",
   "verifyCode":null
}

Important Points

Models are usually much faster than controllers in a well-designed apppcation. Models should −

    Contain business logic.

    Contain vapdation rules.

    Contain attributes.

    Not embed HTML.

    Not directly access requests.

    Not have too many scenarios.

Advertisements