- Yii 教程
 - Yii - 主页
 - Yii - 概述
 - Yii - 安装
 - Yii - 创建页面
 - Yii - 应用程序结构
 - Yii - 入口脚本
 - Yii - 控制器
 - Yii - 使用控制器
 - Yii - 使用动作
 - Yii - 模型
 - Yii - 小部件
 - Yii - 模块
 - Yii - 视图
 - Yii - 布局
 - Yii - 资产
 - Yii - 资产转换
 - Yii - 扩展
 - Yii - 创建扩展
 - Yii - HTTP 请求
 - Yii - 响应
 - Yii - URL 格式
 - Yii - URL 路由
 - Yii - URL 规则
 - Yii - HTML 表单
 - Yii - 验证
 - Yii - 临时验证
 - Yii - AJAX 验证
 - Yii - 会话
 - Yii - 使用闪存数据
 - Yii - cookie
 - Yii - 使用 Cookie
 - Yii - 文件上传
 - Yii - 格式化
 - Yii - 分页
 - Yii - 排序
 - Yii - 属性
 - Yii - 数据提供者
 - Yii - 数据小部件
 - Yii - 列表视图小部件
 - Yii - GridView 小部件
 - Yii - 活动
 - Yii - 创建事件
 - Yii - Behave
 - Yii - 创建Behave
 - Yii - 配置
 - Yii - 依赖注入
 - Yii - 数据库访问
 - Yii - 数据访问对象
 - Yii - 查询生成器
 - Yii - 活动记录
 - Yii - 数据库迁移
 - Yii - 主题化
 - Yii - RESTful API
 - Yii - RESTful API 的实际应用
 - Yii - 字段
 - Yii - 测试
 - Yii - 缓存
 - Yii - 片段缓存
 - Yii - 别名
 - Yii - 日志记录
 - Yii - 错误处理
 - Yii - 身份验证
 - Yii - 授权
 - Yii - 本地化
 - Yii-Gii
 - Gii – 创建模型
 - Gii – 生成控制器
 - Gii – 生成模块
 
- Yii 有用的资源
 - Yii - 快速指南
 - Yii - 有用的资源
 - Yii - 讨论
 
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模型中有五个属性- name、email、subject、body、verifyCode,您可以轻松添加新属性。
属性标签
您经常需要显示与属性关联的标签。默认情况下,属性标签由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,您会注意到标签已更改,如下图所示。
应用场景
您可以在不同的场景中使用模型。例如,当客人想要发送联系表单时,我们需要所有模型属性。当用户想做同样的事情时,他已经登录了,所以我们不需要他的名字,因为我们可以轻松地从数据库中获取它。
为了声明场景,我们应该重写scenario()函数。它返回一个数组,其键是场景名称,值是活动属性。活动属性是要验证的属性。它们也可以被大规模分配。
步骤 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 -在网络浏览器中输入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;
前者干净得多。请注意,大量赋值仅适用于安全属性。它们只是在scene()函数中列出的当前场景属性。
数据导出
模型通常需要以不同的格式导出。要将模型转换为数组,请修改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。
 - 不直接访问请求。
 - 没有太多的场景。