属性
属性代表业务数据。它们可以像数组元素或对象的属性那样来访问。一个模型的每个属性都是公开访问的属性。要指定模型拥有什么属性,应该重写yii\base\Model::attributes() 方法。
<?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; } } ?>
public function actionShowContactModel() { $mContactForm = new \app\models\ContactForm(); $mContactForm->name = "contactForm"; $mContactForm->email = "user@gmail.com"; $mContactForm->subject = "标题"; $mContactForm->body = "内容主体"; var_dump($mContactForm); }
如模型是从 yii\base\Model 扩展,那么它的所有成员变量应该为公共且是非静态的属性。在 ContactForm 模型五个属性 - name, email, subject, body, verifyCode,也可以再添加一些新的。
属性标签
在应用中我们经常需要使用属性相关联来显示标签。默认情况下,属性标签由 yii\base\Model::generateAttributeLabel() 方法自动生成。要手动声明属性标签,可以覆盖yii\base\Model::attributeLabels() 方法。
public function attributeLabels() { return [ 'name' => '名字', 'email' => '邮箱地址', 'subject' => '标题', 'body' => '内容', 'verifyCode' => '验证码', ]; }
模型使用在不同的场景
可以使用模型在不同的场景。 例如,当一个访问用户要发送一份联系表单,我们需要所有的模型属性。 当用户已经登录,我们并不需要他的名字,因为我们可以很容易地从数据库把它读取出来。
要声明场景,应该覆盖 scenarios() 函数。它返回一个数组,其键是场景名称而其值是 Active 属性。Active属性是用来来验证的。它们也可以被大量分配。
<?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' => '名字', 'email' => '电子邮箱', 'subject' => '标题', 'body' => '内容', 'verifyCode' => '验证码', ]; } /** * 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; } } ?>
我们增加了两个场景。一个用于访问游客用户,另一个用于身份验证的用户。当用户通过验证后,再不需要他填入名字。
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步 - 在浏览器访问URL => http://localhost:8080/index.php?r=site/contact 。你应该已经注意到,当前所有模型的属性都是必须的。
$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 = "用户名称"; $mContactForm->email = "user@gmail.com"; $mContactForm->subject = "标题"; $mContactForm->body = "内容"; var_dump($mContactForm->attributes); }
public function actionShowContactModel() { $mContactForm = new \app\models\ContactForm(); $mContactForm->name = "username"; $mContactForm->email = "user@gmail.com"; $mContactForm->subject = "subject"; $mContactForm->body = "body-content"; return \yii\helpers\Json::encode($mContactForm); }

要点
- 包含业务逻辑
- 包含验证规则
- 包含属性
- 不嵌入HTML
- 不能直接访问请求
-
不要有太多的场景