events.md 4.34 KB
Newer Older
1 2 3
Events
======

Alexander Makarov committed
4 5 6
Event is a way to "inject" custom code into existing code at certain places. For example, a comment object can trigger
an "add" event when the user adds a comment. We can write custom code and attach it to this event so that when the event
is triggered (i.e. comment will be added), our custom code will be executed.
7

Alexander Makarov committed
8
Events are very useful both to make your components flexible and to hook into framework and extensions workflow.
9

Alexander Makarov committed
10 11
Triggering events
-----------------
12

Alexander Makarov committed
13
Any component can trigger events using `trigger` method:
14 15

```php
Alexander Makarov committed
16 17 18 19 20 21 22
$this->trigger('myEvent');

// or

$event = new CreateUserEvent(); // extended from yii\base\Event
$event->userName = 'Alexander';
$this->trigger('createUserEvent', $event);
23 24
```

Alexander Makarov committed
25 26 27 28 29 30
Event name should be unique within the class it is defined at. Event names are *case-sensitive*. It is a good practice
to define event names using class constants:

```php
class Mailer extends Component
{
31
    const EVENT_SEND_EMAIL = 'sendEmail';
Alexander Makarov committed
32

33 34 35 36 37
    public function send()
    {
        // ...
        $this->trigger(self::EVENT_SEND_EMAIL);
    }
Alexander Makarov committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
}
```

Attaching event handlers
------------------------

One or multiple PHP callbacks, called *event handlers*, can be attached to an event. When an event is raised, the event
handlers will be invoked automatically in the order they were attached.

There are two main methods of attaching event handlers. It can be done either via code or via application config.

> Tip: In order to get up to date list of framework and extension events search code for `->trigger`.

### Attaching event handlers via code

You can assign event handlers using `on` method of the component instance. The method's first argument is the name of
the event to watch for; the second is the handler to be called when that event occurs:

```php
$component->on($eventName, $handler);
```
59 60 61

The handler must be a valid PHP callback. This could be represented as:

Alexander Makarov committed
62 63 64 65
- The name of a global function.
- An array consisting of a model name and method name.
- An array consisting of an object and a method name.
- An anonymous function.
66 67 68 69 70 71 72 73 74 75 76 77

```php
// Global function:
$component->on($eventName, 'functionName');

// Model and method names:
$component->on($eventName, ['Modelname', 'functionName']);

// Object and method name:
$component->on($eventName, [$obj, 'functionName']);

// Anonymous function:
Alexander Makarov committed
78
$component->on($eventName, function ($event) {
79
    // Use $event.
80 81 82
});
```

83
As shown in the anonymous function example, the event handling function must be defined so that it takes one argument.
84
This will be an [[yii\base\Event]] object.
85

Alexander Makarov committed
86 87 88 89
In order to pass extra data supply it via third argument:

```php
$component->on($eventName, function ($event) {
90
    // the extra data can be accessed via $event->data
Alexander Makarov committed
91 92 93 94 95 96 97 98 99
}, $extraData);
```

### Attaching event handlers via config

It is possible to use application config to attach event hanelers:

```php
return [
100 101 102 103 104 105 106 107 108
    // ...
    'components' => [
        'db' => [
            // ...
            'on afterOpen' => function ($event) {
                // do something right after connected to database
            }
        ],
    ],
Alexander Makarov committed
109 110
];
```
111 112 113 114 115 116 117

Removing Event Handlers
-----------------------

The correspondoing `off` method removes an event handler:

```php
118
$component->off($eventName);
119 120
```

Alexander Makarov committed
121 122
Yii supports the ability to associate multiple handlers with the same event. When using `off` as in the above,
every handler is removed. To remove only a specific handler, provide that as the second argument to `off`:
123 124

```php
125
$component->off($eventName, $handler);
126 127
```

128 129 130 131 132
The `$handler` should be presented in the `off` method in the same way as was presented in `on` in order to remove it.

Global Events
-------------

Alexander Makarov committed
133 134
You can use "global" events instead of per-component ones. To trigger a global event use an application instance instead
of specific component:
135 136

```php
Alexander Makarov committed
137
Yii::$app->trigger($eventName);
138 139
```

Alexander Makarov committed
140
In order to attach a handler to it use the following:
141 142

```php
Alexander Makarov committed
143
Yii::$app->on($eventName, $handler);
144 145
```

146 147 148
Class Events
------------

Alexander Makarov committed
149 150
It is possible to attach event handlers to all instances of a class instead of individual instances. To do so, use
the static `Event::on` method:
151 152 153

```php
Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
154
    Yii::trace(get_class($event->sender) . ' is inserted.');
155 156 157 158
});
```

The code above defines a handler that will be triggered for every Active Record object's `EVENT_AFTER_INSERT` event.