yii2 行为
behavior 是 yii\base\Behavior
或其子类的实例, behavior,可以无须改变类继承关系即可增强一个已有的 yii\base\Component
类功能。当行为附加到组件后,它将“注入”它的方法和属性到组件,然后可以像访问组件内定义的方法和属性一样访问它们。 此外,行为通过组件能响应被触发的事件, 从而自定义或调整组件正常执行的代码。
定义行为
~/yiint/components/MyBehavior.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?php /** * 自定义行为,用于行为功能的演示 */ namespace app\components; use yii\base\Behavior; /** * 行为 演示 */ class MyBehavior extends Behavior { public $prop1; private $_prop2; public function getProp2() { return $this->_prop2; } public function setProp2($value) { $this->_prop2 = $value; } public function foo() { // ... } } |
以上代码定义了行为类 @app\components\MyBehavior
并为要附加行为的组件提供了两个属性 prop1 、 prop2 和一个方法 foo()。
附加行为
静态附加行为
覆写行为要附加的组件类的 yii\base\Component::behaviors()
方法, 返回行为配置列表。
每个行为配置格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
return [ // 匿名行为,只有行为类名 MyBehavior::className(), // 通过指定行为配置数组相应的键可以给行为关联一个名称, 这种行为称为命名行为 // 命名行为,只有行为类名 'myBehavior2' => MyBehavior::className(), // 匿名行为,配置数组 [ 'class' => MyBehavior::className(), 'prop1' => 'value1', 'prop2' => 'value2', ], // 命名行为,配置数组 'myBehavior4' => [ 'class' => MyBehavior::className(), 'prop1' => 'value1', 'prop2' => 'value2', ] ]; |
动态附加行为
在对应组件里调用 yii\base\Component::attachBehavior()
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 附加行为对象 $component->attachBehavior('myBehavior1', new MyBehavior); // 附加行为类 $component->attachBehavior('myBehavior2', MyBehavior::className()); // 附加配置数组 $component->attachBehavior('myBehavior3', [ 'class' => MyBehavior::className(), 'prop1' => 'value1', 'prop2' => 'value2', ]); |
可以通过 yii\base\Component::attachBehaviors()
方法一次附加多个行为:
1 2 3 4 5 |
$component->attachBehaviors([ 'myBehavior1' => new MyBehavior, // 命名行为 MyBehavior::className(), // 匿名行为 ]); |
使用行为
将behavior 附加到 yii\base\Component
类或其子类后就可以直接使用它。
1 2 3 4 5 6 |
// "prop1" 是定义在行为类的属性 echo $component->prop1; $component->prop1 = $value; // foo() 是定义在行为类的公共方法 $component->foo(); |
行为对象
附加行为到组件时的命名行为, 可以使用这个名称来访问行为对象
1 2 3 4 5 |
$behavior = $component->getBehavior('myBehavior'); // 获取附加到这个组件的所有行为: $behaviors = $component->getBehaviors(); |
移除行为
要移除行为,可以调用 yii\base\Component::detachBehavior()
方法用行为相关联的名字实现:
1 2 3 4 |
$component->detachBehavior('myBehavior1'); // 移除全部行为: $component->detachBehaviors(); |
使用 TimestampBehavior
yii\behaviors\TimestampBehavior
行为支持在 yii\db\ActiveRecord 存储时自动更新它的时间戳属性。
首先,附加这个行为到计划使用该行为的 yii\db\ActiveRecord 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
namespace app\models\User; use yii\db\ActiveRecord; use yii\behaviors\TimestampBehavior; class User extends ActiveRecord { // ... public function behaviors() { return [ [ 'class' => TimestampBehavior::className(), 'attributes' => [ ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], ], // if you're using datetime instead of UNIX timestamp: // 'value' => new Expression('NOW()'), ], ]; } } |
以上指定的行为数组:
当记录插入时, 行为将当前的 UNIX 时间戳赋值给 created_at 和 updated_at 属性;
当记录更新时,行为将当前的 UNIX 时间戳赋值给 updated_at 属性。
保存 User 对象, 将会发现它的 created_at 和 updated_at 属性自动填充了当前时间戳:
1 2 3 4 5 6 7 8 |
$user = new User; $user->email = 'test@example.com'; $user->save(); echo $user->created_at; // 显示当前时间戳 yii\behaviors\TimestampBehavior 行为还提供了一个有用的方法 yii\behaviors\TimestampBehavior::touch(), 这个方法能将当前时间戳赋值给指定属性并保存到数据库: $user->touch('login_time'); |
处理事件
如果要让行为响应对应组件的事件触发, 就应覆写 yii\base\Behavior::events()
方法,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
namespace app\components; use yii\db\ActiveRecord; use yii\base\Behavior; class MyBehavior extends Behavior { // 其它代码 public function events() { return [ ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate', ]; } public function beforeValidate($event) { // 处理器方法逻辑 } } |
yii\base\Behavior::events()
方法返回事件列表和相应的处理器。 上例声明了 yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE
事件和它的处理器 beforeValidate()
。