Emitter
The Emitter is a simple pattern that allows you to create an object that emits events, and allow you to listen to those events.
Example:
use Sabre\Event\Emitter;
$emitter = new Emitter();
// Subscribing
$emitter->on('create', function() {
echo "Something got created, apparently\n"
});
// Publishing
$emitter->emit('create');
The name of the event (create
) can be any free-form string.
Priorities
By supplying a priority, you are ensured that subscribers are handled in a specific order. The default priority is 100. Anything below that will be triggered earlier, anything higher later.
If there's two subscribers with the same priority, they will execute in an undefined, but deterministic order.
$emitter->on('create', function() {
// This event will be handled first.
}, 50);
Callbacks
All default PHP callbacks are supported, so closures are not required.
$emitter->on('create', 'myFunction');
$emitter->on('create', ['myClass', 'myMethod']);
$emitter->on('create', [$myInstance, 'myMethod']);
Canceling the event handler
If any callback returns false
the event chain is stopped immediately.
A use case is to use a listener to check if a user has permission to perform a certain action, and stop execution if they don't.
$emitter->on('create', function() {
if (!checkPermission()) {
return false;
}
}, 10);
Emitter::emit()
will return false
if the event was cancelled, and
true
if it wasn't.
Throwing an exception will also stop the chain.
This is similar to Javascript's preventDefault().
Passing arguments
Arguments can be passed as an array.
$emitter->on('create', function($entityId) {
echo "An entity with id ", $entityId, " just got created.\n";
});
$entityId = 5;
$emitter->emit('create', [$entityId]);
Because you cannot really do anything with the return value of a listener, you can pass arguments by reference to communicate between listeners and back to the emitter.
$emitter->on('create', function($entityId, &$warnings) {
echo "An entity with id ", $entityId, " just got created.\n";
$warnings[] = "Something bad may or may not have happened.\n";
});
$warnings = [];
$emitter->emit('create', [$entityId, &$warnings]);
print_r($warnings);
Wildcards
Since sabre/event 4.0.0, there is also a WildcardEmitter
that supports
listening for wildcard events.
Example:
use Sabre\Event\WildcardEmitter;
$emitter = new WildcardEmitter();
$emitter->on('create:*', function() {
});
$emitter->emit('create:bicycle');
The reason that the WildcardEmitter
is a separate object, is because it's
slightly slower. This is only important for applications that need extremely
high performance from their event system.
The WildcardEmitter
is still really fast, and that's partially because it
only supports having the wildcard as the last character. Events such as:
foo:*:bar
are not supported.
In the past two examples the colon (:
) is used as a separator. In reality
this is completely up to you, and you may even omit it entirely.
Integration into other objects
To add Emitter
capabilities to any class, you can simply extend it.
If you cannot extend, because the class is already part of an existing class hierarchy you can use the supplied trait.
use Sabre\Event;
class MyNotUneventfulApplication
extends AppController
implements Event\EmitterInterface
{
use Event\EmitterTrait;
}
In the preceding example, MyNotUneventfulApplication
has all the
capabilities of Emitter
.