Overview
EventManger is a component designed for the following use cases:
Implementing a simple subject/observer pattern
Implementing aspect-oriented design
Implementing event-driven Architecture
The basic architecture allows you to add and remove listeners for specified events, either on an instance basis or in a shared collection; trigger events; and terminate listener execution.
Quick Start
Normally, you will create an EventManager in a class.
use Zend\EventManager\EventManagerInterface; use Zend\EventManager\EventManager; use Zend\EventManager\EventManagerAwareInterface; class Foo implements EventManagerAwareInterface { protected $events; public function setEventManager(EventManagerInterface $events) { $events->setIdentifiers(array( __CLASS__, get_called_class(), )); $this->events = $events; return $this; } public function getEventManager() { if (null === $this->events) { $this->setEventManager(new EventManager()); } return $this->events; } }
The above code allows the user to access the EventManager instance, or reset it with a new instance; if it does not exist, it will be lazily instantiated when it is used.
EventManager is only interested in whether it triggered some events. The basic trigger accepts three parameters: the name of the event, which is usually the current function/method name; the context, which is usually the current object instance; and the parameters, which are usually the parameters provided to the current function/method.
class Foo { // ... assume events definition from above public function bar($baz, $bat = null) { $params = compact('baz', 'bat'); $this->getEventManager()->trigger(__FUNCTION__, $this, $params); } }
In order, triggering an event only cares about whether something is listening for the event. A listener is added to the EventManager, specifying a specific event and the callback to be notified. The callback accepts an Event object, which has accessors for getting the event name, context, and parameters. Let's add a listener and fire the event.
use Zend\Log\Factory as LogFactory; $log = LogFactory($someConfig); $foo = new Foo(); $foo->getEventManager()->attach('bar', function ($e) use ($log) { $event = $e->getName(); $target = get_class($e->getTarget()); $params = json_encode($e->getParams()); $log->info(sprintf( '%s called on %s, using params %s', $event, $target, $params )); }); // Results in log message: $foo->bar('baz', 'bat'); // reading: bar called on Foo, using params {"baz" : "baz", "bat" : "bat"}"
Note that the second argument to attach() is any valid callback; the example shows an anonymous function to keep the example self-contained. However, you can also use a valid function name, a function object, a string referencing a static method, or a callback array with a specific static method or instance method. Once again, any PHP callback is valid.
Sometimes you may want to specify a listener without creating an object instance of the EventManager class. Zend Framework implements it through the concept of SharedEventCollection. Simply put, you can use a well-known SharedEventCollection to inject a standalone EventManager instance, and the EventManager instance will be queried for additional listeners. Listeners added to a SharedEventCollection are roughly the same as normal event managers; calling attach is exactly the same as EventManager, but requires an additional parameter at the beginning: a specified instance. Remember when creating an instance of EventManager, how did we pass it __CLASS__? When using a SharedEventCollection, that value, or any string in the array you provide to the constructor, may be used to identify an instance. As an example, assuming we have a SharedEventManager instance that we know has been injected into our EventManager instance (for instances, via dependency injection), we can change the above example to add it via a shared collection:
use Zend\Log\Factory as LogFactory; // Assume $events is a Zend\EventManager\SharedEventManager instance $log = LogFactory($someConfig); $events->attach('Foo', 'bar', function ($e) use ($log) { $event = $e->getName(); $target = get_class($e->getTarget()); $params = json_encode($e->getParams()); $log->info(sprintf( '%s called on %s, using params %s', $event, $target, $params )); }); // Later, instantiate Foo: $foo = new Foo(); $foo->getEventManager()->setSharedEventCollection($events); // And we can still trigger the above event: $foo->bar('baz', 'bat'); // results in log message: // bar called on Foo, using params {"baz" : "baz", "bat" : "bat"}"
Note: StaticEventManager
In 2.0.0beta3, you can use the StaticEventManager singleton as a SharedEventCollection. This way, you don't need to worry about where or how to access the SharedEventCollection; it's globally available by simply calling StaticEventManager::getInstance().
Be aware, however, that the framework deprecates its use, and in 2.0.0beta4 you will replace it by configuring a SharedEventManager instance and injecting it into a separate EventManager instance.
Wildcard Listeners
Sometimes you may want to add the same listener for many or all events for a given instance, or perhaps, use a shared event collection , lots of context, and lots of events. The EventManager component allows this.
Add multiple events at once
$events = new EventManager(); $events->attach(array('these', 'are', 'event', 'names'), $callback);
Add by wildcard
$events = new EventManager(); $events->attach('*', $callback);
Note that if you specify a priority, that priority will be used for this listener to trigger any event.
The above code specifies that any time a trigger is triggered will result in a notification for this specific listener.
Add multiple events at once through a SharedEventManager
$events = new SharedEventManager(); // Attach to many events on the context "foo" $events->attach('foo', array('these', 'are', 'event', 'names'), $callback); // Attach to many events on the contexts "foo" and "bar" $events->attach(array('foo', 'bar'), array('these', 'are', 'event', 'names'), $callback);
Note that if you specify a priority, that priority will be used for all specified events.
Add all events at once through a SharedEventManager
$events = new SharedEventManager(); // Attach to all events on the context "foo" $events->attach('foo', '*', $callback); // Attach to all events on the contexts "foo" and "bar" $events->attach(array('foo', 'bar'), '*', $callback);
Note that if you specify a priority, that priority will be used for all specified events.
The above code specifies the context "foo" and "bar", and the specified listener will be notified when any event is triggered.
Configuration Options
EventManager Options
Identifier
The given EventManager instance can answer a string or an array of strings, when accessed through a SharedEventManager hour.
event_class
The name of an alternative Event class used to represent events passed to listeners.
shared_collections
A SharedEventCollection instance when an event is triggered.
Available methods
__construct
__construct(null|string|int Sidentifier)
Construct a new EventManager instance using the given identifier, If provided, for the purpose of sharing the collection.
setEventClass
setEventClass(string $class)
Provides the name of the replacement Event class to use when creating events that are passed to triggered listeners.
setSharedCollections
setSharedCollections(SharedEventCollection $collections=null)
SharedEventCollection instance used when the event is triggered.
getSharedCollections
getSharedCollections()
Returns the SharedEventCollection instance currently added to. If no collection is added, returns empty, or a SharedEventCollection instance.
trigger
trigger(string $event, mixed $target, mixed $argv, callback $callback)
Trigger all listeners for the specified event. It is recommended to use the current function/method name for $event, followed by ".pre", ".post", etc., if necessary. $context should be an instance of the current object, or the name of the function if it is not triggered using an object. $params should usually be an associative array or ArrayAccess instance; we recommend using parameters passed to functions/methods (compact() is often useful here). This method can also accept a callback and behaves the same as triggerUntil().
The method returns an instance of a ResponseCollection, which can be used to introspect the values returned by a variety of listeners, test for short-circuiting, and more.
triggerUntil
triggerUntil(string $event, mixed $context, mixed $argv, callback $callback)
Trigger all listeners for the specified event, just like trigger( ), additionally it passes the return value of each listener to $callback; if $callback returns a boolean true value, the listener's execution will be terminated. You can use $result->stopped() to test this.
attach
attach(string $event, callback $callback, int $priority)
Add $callback to the EventManager instance and listen for the event $event. If a $priority is provided, the listener will be inserted into the internal listener stack using that priority; higher values will be executed first. (The default priority is "1", and runs with negative values.) The
method returns an instance of Zend\Stdlib\CallbackHandler; this value can later be passed to detach() if needed .
attachAggregate
attachAggregate(string|ListenerAggregate $aggregate)
If a string is passed as $aggregate, instantiate that class. $aggregate is then passed to the attach() method of the EventManager instance so it can register the listener.
Return ListenerAggregate instance.
detach
detach(CallbackHandler $listener)
Scan all listeners and detach any listeners that match $listener so they will no longer be triggered.
Returns a true boolean value if any listener has been assigned and unsubscribed, otherwise returns a false boolean value.
detachAggregate
detachAggregate(ListenerAggregate $aggregate)
Loop through all events to determine the listener represented by the collection; for all matches, the listener will be Remove.
Returns a true boolean value if any listener is identified and unsubscribed, otherwise returns a false boolean value.
getEvents
getEvent()
Returns an array with the names of all events attached by the listener.
getListeners
getListeners(string $event)
Returns a Zend\Stdlib\PriorityQueue instance for all listeners added to $event
clearListeners
clearListeners(string $event)
Remove all listeners added to $event.
prepareArgs
prepareArgs(array $args)
Creates an ArrayObject from the provided $args. This is useful if you want your listener to be able to change parameters so that later listeners or triggered methods can see these changes.
For more articles related to the Zend Framework 2.0 Event Manager (The EventManager) introductory tutorial, please pay attention to the PHP Chinese website!