behaviors.md 3.74 KB
Newer Older
1 2 3
Behaviors
=========

4
A behavior (also knows as *mixin*) can be used to enhance the functionality of an existing component without modifying the component's
Qiang Xue committed
5
code. In particular, a behavior can "inject" its public methods and properties into the component, making them directly accessible
kate-kate committed
6
via the component itself. A behavior can also respond to  events triggered in the component, thus intercepting the normal
7
code execution. Unlike [PHP's traits](http://www.php.net/traits), behaviors can be attached to classes at runtime.
8 9 10 11

Using behaviors
---------------

12 13
A behavior can be attached to any class that extends from [[yii\base\Component]]. In order to attach a behavior to a class,
the component class must implement the `behaviors`
Qiang Xue committed
14
method. As an example, Yii provides the [[yii\behaviors\TimestampBehavior]] behavior for automatically updating timestamp
15
fields when saving an [[yii\db\ActiveRecord|Active Record]] model:
16 17

```php
Qiang Xue committed
18 19
use yii\behaviors\TimestampBehavior;

20 21 22 23 24 25 26 27
class User extends ActiveRecord
{
	// ...

	public function behaviors()
	{
		return [
			'timestamp' => [
Qiang Xue committed
28
				'class' => TimestampBehavior::className(),
29
				'attributes' => [
Alexander Kochetov committed
30 31
					ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
					ActiveRecord::EVENT_BEFORE_UPDATE => 'updated_at',
32 33 34 35 36 37 38
				],
			],
		];
	}
}
```

Qiang Xue committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
In the above, the name `timestamp` can be used to reference the behavior through the component. For example, `$user->timestamp`
gives the attached timestamp behavior instance. The corresponding array is the configuration used to create the
[[yii\behaviors\TimestampBehavior|TimestampBehavior]] object.

Besides responding to the insertion and update events of ActiveRecord, `TimestampBehavior` also provides a method `touch()`
that can assign the current timestamp to a specified attribute. As aforementioned, you can access this method directly
through the component, like the following:

```php
$user->touch('login_time');
```

If you do not need to access a behavior object, or the behavior does not need customization, you can also
use the following simplified format when specifying the behavior,

```php
use yii\behaviors\TimestampBehavior;

class User extends ActiveRecord
{
	// ...

	public function behaviors()
	{
		return [
			TimestampBehavior::className(),
			// or the following if you want to access the behavior object
			// 'timestamp' => TimestampBehavior::className(),
		];
	}
}
```
71

72 73 74 75

Creating your own behaviors
---------------------------

76
To create your own behavior, you must define a class that extends [[yii\base\Behavior]].
77 78

```php
79 80 81 82 83
namespace app\components;

use yii\base\Behavior;

class MyBehavior extends Behavior
84 85 86 87
{
}
```

Qiang Xue committed
88
To make it customizable, like [[yii\behaviors\TimestampBehavior]], add public properties:
89 90

```php
91 92 93 94 95
namespace app\components;

use yii\base\Behavior;

class MyBehavior extends Behavior
96 97 98 99 100 101 102 103
{
	public $attr;
}
```

Now, when the behavior is used, you can set the attribute to which you'd want the behavior to be applied:

```php
104 105 106 107
namespace app\models;

use yii\db\ActiveRecord;

108 109 110 111 112 113 114 115
class User extends ActiveRecord
{
	// ...

	public function behaviors()
	{
		return [
			'mybehavior' => [
116
				'class' => 'app\components\MyBehavior',
117 118 119 120 121 122 123
				'attr' => 'member_type'
			],
		];
	}
}
```

124 125
Behaviors are normally written to take action when certain events occur. Below we're implementing `events` method
to assign event handlers:
126 127

```php
128 129 130 131 132 133
namespace app\components;

use yii\base\Behavior;
use yii\db\ActiveRecord;

class MyBehavior extends Behavior
134 135
{
	public $attr;
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

	public function events()
	{
		return [
			ActiveRecord::EVENT_BEFORE_INSERT => 'beforeInsert',
			ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeUpdate',
		];
	}

	public function beforeInsert() {
		$model = $this->owner;
		// Use $model->$attr
	}

	public function beforeUpdate() {
		$model = $this->owner;
152 153 154
		// Use $model->$attr
	}
}
Alexander Kochetov committed
155
```