Yii - 模型

  • 简述

    模型是表示业务逻辑和规则的对象。要创建模型,您应该扩展yii\base\Model类或其子类。
  • 属性

    属性代表业务数据。它们可以像数组元素或对象属性一样被访问。每个属性都是模型的可公开访问的属性。要指定一个模型拥有什么属性,你应该重写yii\base\Model::attributes()方法。
    让我们看一下基本应用程序模板的ContactForm模型。
    
    <?php
       namespace app\models;
       use Yii;
       use yii\base\Model;
       /**
       * ContactForm is the model behind the contact form.
       */
       class ContactForm extends Model {
          public $name;
          public $email;
          public $subject;
          public $body;
          public $verifyCode;
          /**
          * @return array the validation rules.
          */
          public function rules() {
             return [
                // name, email, subject and body are required
                [['name', 'email', 'subject', 'body'], 'required'],
                // email has to be a valid email address
                ['email', 'email'],
                // verifyCode needs to be entered correctly
                ['verifyCode', 'captcha'],
             ];
          }
          /**
          * @return array customized attribute labels
          */
          public 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 validation
          */
          public function contact($email) {
             if ($this->validate()) {
                Yii::$app->mailer->compose()
                   ->setTo($email)
                   ->setFrom([$this->email => $this->name])
                   ->setSubject($this->subject)
                   ->setTextBody($this->body)
                   ->send();
                return true;
             }
             return false;
          }
       }
    ?>
    
    第 1 步-使用以下代码在SiteController中创建一个名为actionShowContactModel的函数。
    
    public function actionShowContactModel() { 
       $mContactForm = new \app\models\ContactForm(); 
       $mContactForm->name = "contactForm"; 
       $mContactForm->email = "user@gmail.com"; 
       $mContactForm->subject = "subject"; 
       $mContactForm->body = "body"; 
       var_dump($mContactForm); 
    }
    
    在上面的代码中,我们定义了ContactForm模型,设置属性,并将模型显示在屏幕上。
    第 2 步- 现在,如果您在 Web 浏览器的地址栏中键入http://localhost:8080/index.php?r=site/show-contact-model,您将看到以下内容。
    显示联系人视图
    如果您的模型从yii\base\Model扩展,那么它的所有成员变量(公共和非静态)都是属性。ContactForm模型中有五个属性- 姓名、电子邮件、主题、正文、验证代码,您可以轻松添加新属性。
  • 属性标签

    您经常需要显示与属性关联的标签。默认情况下,属性标签由yii\base\Model::generateAttributeLabel()方法自动生成。要手动声明属性标签,您可以覆盖yii\base\Model::attributeLabels()方法。
    第 1 步- 如果您打开http://localhost:8080/index.php?r=site/contact,您将看到以下页面。
    联系表
    请注意,属性标签与其名称相同。
    第 2 步 - 现在,通过以下方式修改ContactForm模型中的attributeLabels函数。
    
    public function attributeLabels() {
       return [
          'name' => 'name overridden',
          'email' => 'email overridden',
          'subject' => 'subject overridden',
          'body' => 'body overridden',
          'verifyCode' => 'verifyCode overridden',
       ];
    }
    
    第 3 步- 如果再次打开http://localhost:8080/index.php?r=site/contact,您会注意到标签已更改,如下图所示。
    联系人已更改
  • 场景

    您可以在不同的场景中使用模型。例如,当客人想要发送联系表格时,我们需要所有模型属性。当用户想要做同样的事情时,他已经登录了,所以我们不需要他的名字,因为我们可以很容易地从数据库中获取它。
    要声明场景,我们应该重写场景()函数。它返回一个数组,其键是场景名称,值是活动属性。活动属性是要验证的。他们也可以被大量分配
    第 1 步 - 通过以下方式修改ContactForm模型。
    
    <?php
       namespace app\models;
       use Yii;
       use yii\base\Model;
       /**
       * ContactForm is the model behind the contact form.
       */
       class ContactForm extends Model {
          public $name;
          public $email;
          public $subject;
          public $body;
          public $verifyCode;
          const SCENARIO_EMAIL_FROM_GUEST = 'EMAIL_FROM_GUEST';
          const SCENARIO_EMAIL_FROM_USER = 'EMAIL_FROM_USER';
          public 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 validation rules.
          */
          public function rules() {
             return [
                // name, email, subject and body are required
                [['name', 'email', 'subject', 'body'], 'required'],
                // email has to be a valid email address
                ['email', 'email'],
                // verifyCode needs to be entered correctly
                ['verifyCode', 'captcha'],
             ];
          }
          /**
          * @return array customized attribute labels
          */
          public 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 validation
          */
          public function contact($email) {
             if ($this -> validate()) {
                Yii::$app->mailer->compose()
                   ->setTo($email)
                   ->setFrom([$this->email => $this->name]) 
                   ->setSubject($this->subject) 
                   ->setTextBody($this->body)
                   ->send();
                return true;
             }
             return false;
          }
       }
    ?>
    
    我们添加了两个场景。一个用于访客,另一个用于经过身份验证的用户。当用户被认证时,我们不需要他的名字。
    第 2 步- 现在,修改SiteController的actionContact函数。
    
    public 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,
       ]);
    }
    
    第 3 步-在 Web 浏览器中键入http://localhost:8080/index.php?r=site/contact 。您会注意到,目前,所有模型属性都是必需的。
    必需的模型属性
    第 4 步- 如果您在actionContact中更改模型的场景,如以下代码所示,您会发现不再需要 name 属性。
    
    $model->scenario = ContactForm::SCENARIO_EMAIL_FROM_USER;
    
    改变情景
  • 大量作业

    大规模分配是一种通过单行代码从多个输入属性创建模型的便捷方式。
    代码行是 -
    
    $mContactForm = new \app\models\ContactForm; 
    $mContactForm->attributes = \Yii::$app->request->post('ContactForm');
    
    上面给出的代码行相当于 -
    
    $mContactForm = new \app\models\ContactForm; 
    $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;
    
    前者更干净。请注意,大量赋值仅适用于安全属性。它们只是在scenario()函数中列出的当前场景属性。
  • 数据导出

    模型通常需要以不同的格式导出。要将模型转换为数组,请修改SiteController的actionShowContactModel函数-
    
    public function actionShowContactModel() {
       $mContactForm = new \app\models\ContactForm();
       $mContactForm->name = "contactForm";
       $mContactForm->email = "user@gmail.com";
       $mContactForm->subject = "subject";
       $mContactForm->body = "body";
       var_dump($mContactForm->attributes);
    } 
    
    在地址栏中输入http://localhost:8080/index.php?r=site/show-contact-model,您将看到以下内容 -
    数据导出
    要将模型转换为JSON格式,请按以下方式修改actionShowContactModel函数 -
    
    public function actionShowContactModel() {
       $mContactForm = new \app\models\ContactForm();
       $mContactForm->name = "contactForm";
       $mContactForm->email = "user@gmail.com";
       $mContactForm->subject = "subject";
       $mContactForm->body = "body";
       return \yii\helpers\Json::encode($mContactForm);
    }
    
    浏览器输出-
    
    {
       "name":"contactForm",
       "email":"user@gmail.com",
       "subject":"subject",
       "body":"body ",
       "verifyCode":null
    }
    
  • 要点

    在精心设计的应用程序中,模型通常比控制器快得多。模型应该 -
    • 包含业务逻辑。
    • 包含验证规则。
    • 包含属性。
    • 不嵌入 HTML。
    • 不直接访问请求。
    • 没有太多的场景。