models
是展示业务数据、规则和逻辑的对象。
你可以通过扩展yii\base\Model
或者其子类来创建model
类, 这个基类支持下面的特性:
Attributes
Attribute labels
Massive assignment
Validation rules
Data Exporting
Model Class
还是某些更复杂的模型的基类,比如Active Record
原创文章, 转载请注明 http://www.cnblogs.com/ganiks/
3.6.1 Attributes访问属性并没有强制说你一定要让你的模型类基于
yii\base\Model
,但是因为有很多的Yii的组件都是支持yii\base\Model
的, 建议你还是基于它来构建你的模型。
yii\base\Model::attributes()
制定了这个模型类含有哪些属性, 访问其属性如下:
$model = new \app\models\ContactForm;$model->name = 'example';echo $model->name;
也可以如下访问属性:
$model = new \app\models\ContactForm;$model['name'] = 'example';echo $model['name'];foreach($model as $name=>$value){ echo "$name:$value\n";}
这要多谢 yii\base\Model
对Arrayaccess
和ArrayIterator
的支持。http://php.net/manual/en/class.arrayaccess.phphttp://php.net/manual/en/class.arrayiterator.php
默认的, 如果你的 model
直接扩展自yii\base\Model
, 那么它所有的 non-static public
成员都是属性。例如,下面这个就有4个属性。
namespace app\models;use yii\base\Model;class ContactForm extends Model{ public $name; public $email; public $subject; public $body;}
你也可以通过定义yii\base\Model::attributes()
方法来定义属性, 但是通常不这样做,即使在ActiveRecord
中,也常常是用tableName()
来直接返回一个表名。
public static function tableName() { return '{{%user}}'; }
属性标签$model = new \app\models\ContactForm;echo $model->getAttributeLabel('name');
默认的, 这些labes是由方法yii\base\Model::generateAttributeLabel()
自动生成, 经过转换 ,firstName
=>First Name
你也可以自定义:
public function attributeLabels() { return [ 'name' => 'Your name', 'email' => 'Your email address', 'subject' => \Yii::t('app', 'Subject'), ]; }
3.6.2 Scenarios场景是个很有用的东西,能够让一个model
在不同的情况下灵活使用。
举例来说, 一个User
模型可能用于采集用户登录的输入,也可以用于注册。在不同的情况下, 一个模型可能使用不同的业务和逻辑。比如,email
属性可能在用户注册时候才是必填的。
模型使用属性yii\base\Model::scenario
来记载目前所处的场景。默认的, 用的是一个default
场景。
下面是两种设置场景的方式:
$model = new User;$model->scenario = 'login';$model = new User(['scenario' => 'login']);
默认的, 一个模型支持的场景是由其validataion rules
中声明的。但是,你也可以通过重写下面的方法来自定义这个行为:
class User extends ActiveRecord{ public function scenarios() { return [ 'login' => ['username', 'passWord'], 'register' => ['username', 'email', 'password'] ]; }}
多场景的模型多用于
ActiveRecord
类模型。
scenarios()
方法返回的是一个数组,键是场景名字,值则是相应的active attributes
。
默认的像上面这样的scenarios()
返回的是在yii\base\Model::rules()
中声明的验证规则中的所有的场景;而如果你要引入新的场景,则应该这样做:
class User extends ActiveRecord{ public function scenarios() { $scenarios = parent::scenarios(); $scenarios['login'] = ['username', 'password']; ... return $scenarios; }}
场景这个特性,主要用于“验证”和“批零赋值”,也可以用于“指定labels”
3.6.3 Validation Rules调用validate
yii\base\Model::validate()if($model->validate()){ ...}
声明validation rules
yii\base\Model::rules()public function rules(){ return [ [['name', 'email', 'subject', 'body'], 'required', 'on' => 'register'], ['email', 'email'] ];}
3.6.4 Massive Assignment一个属性要想被validate(), 需要符合2个条件, 它在
scenarios()
中被声明为active attribute
; 跟rules()
中声明的一个或者多个active rules
相关联另外, 如果属性没有自定on
,则默认是适用于所有的场景
批量赋值,是一个方便的方法,可以用一行代码就让model跟用户的输入结合起来。它直接的把用户的输入赋给了yii\base\Model::attributes
属性。
下面是两种方式,很明显, 前者更简洁:
$model = new ContactForm;$model->attributes = Yii::$app->request->post('ContactForm');$model = new ContactForm;$data = Yii::$app->request->post('ContactForm', []);$model->name = iseet($data['name']) ? $data['name'] : null ;... ...... ...
Safe Attributes 安全属性批量赋值,只作用于所谓的“安全属性”, 也就是在yii\base\Model::scenarios()
中列出的属性;而其他的属性则不会有所动。
安全属性这个特性的好处在于,方便你控制那些属性可以被终端用户操作。
由于默认的yii\base\Model::scenarios()
会返回yii\base\Model::rules()
中所有的场景和属性,如果你重写这个方法,意味着只要出现在rules()
中的属性,就都是安全属性。那如果我想要的安全属性并不需要定义什么验证规则怎么办呢?基于这个原因,yii提供了safe
来让你单独声明安全属性的规则
public function rules(){ return [ [['title', 'description'], 'safe'], ];}
Unsafe Attributes 非安全属性如上所述, yii\base\Model::scenarios()
有两个目的:
而有些极少数的情况下, 你可能想要validate一个属性而并不想让其safe
public function scenarios(){ return [ 'login' => ['username', 'password', '!secret'], ];}
3.6.5 Data Exporting模型经常需要被导出为不同的格式。比如你可能想要将一系列的模型转换到JSON或者Excel。
导出过程可以分为2步:
第二步很简单,可以通过类似实现yii\web\JsonResponseFormatter
;主要是第一步, 最简单的方法是yii\base\Model::attributes
$post = \app\models\Post::findOne(100);$array = $post->attributes;
还有一个更复杂的方法(用于RESTful API)中, 叫做 yii\base\Model::toArray()
, 这个方法强大之处在于, 允许你决定最终的结果中包含哪些项目,叫做fileds
,并且可以指定如何format
fields
public function fields(){ return [ 'id', 'email' => 'email_address', 'name' => function(){ return $this->first_name.' '. $this->last_name; } ];}public function fields(){ $fields = parent::fields(); unset($fields['auth_key'], $fields['password_hash']); return $fields;}