Documentation

Events

Download (pdf)

Overview

Events provide a simple observer implementation, allowing one to subscribe and listen for events in the application.

The Event

When an event is triggered, it's identified by a unique name (e.g. system.onRoute), which any number of listeners might be listening to. An Event instance is also created and passed to all of the listeners.

Naming Conventions

The unique event name can be any string, but optionally follows a few simple naming conventions:

  • use only lowercase letters, numbers, dots (.) and underscores (_);
  • prefix names with a namespace followed by a dot (e.g. kernel.);
  • end names with a verb that indicates what action is being taken (e.g. request).

Event Object

When the dispatcher notifies listeners, it passes an actual Event object to those listeners. The base Event class is very simple: it contains a method for stopping event propagation, methods for adding and removing arguments (i.e., data to be passed to the listeners), and a method for adding to the response.

Often times, data about a specific event needs to be passed along with the Event object so that the listeners have needed information.

// Creating an Event called "onSomething".
$event = new Hubzero\Events\Event('system.onDoSomething');

// Adding an argument named "foo" with value "bar".
$event->addArgument('foo', 'bar');

Arguments can be added (if not already existing), forcefully set, retrieved, or removed.

addArgument
Add an event argument, only if it is not existing.
setArgument
Set the value of an event argument. If the argument already exists, it will be overridden.
removeArgument
Remove an event argument.
getArgument
Get an event argument value.
hasArgument
Tell if the given event argument exists.
class EventListener
{
    public function onDoSomething($event)
    {
        // Check that the event has the necessary 'foo' argument
        if ( ! $event->hasArgument('foo'))
        {
            return;
        }

        // Get the 'foo' argument
        $foo = $event->getArgument('foo');
    }
}

The Dispatcher

The dispatcher is the central object of the event dispatcher system. In general, a single dispatcher is created, which maintains a registry of listeners. When an event is triggered via the dispatcher, it notifies all listeners registered with that event:

$dispatcher = new Hubzero\Events\Dispatcher();

Registering Listeners

Registering an event listener can be done simply by passing the listener object to the addListener method.

$dispatcher->addListener(new SystemListener);

By default, the listener will be registered to all events matching its method names. If the listener contains methods that should not be registered, a defined list of events may be passed.

$dispatcher->addListener(
    new SystemListener,
    array(
        'onBeforeRoute' => Hubzero\Events\Priority::NORMAL,
        'onAfterRoute' => Hubzero\Events\Priority::NORMAL,
    )
);

In the above example, the SystemListener object is registered as an even listener along with a specified list of events that it listens to. When a defined list of events is passed, a listener's priority for a given Event is also specified.

When a Listener is added without specifying the event names, it is registered with a NORMAL priority to all events. If some listeners have the same priority for a given event, they will be called in the order they were added to the Dispatcher.

It is also possible to register a closure or anonymous function as an event listener:

$dispatcher->addListener(
    function($event) {
        $foo = $event->getArgument('foo');
        // ... do cool things here ...
    },
    array(
        'onBeforeRoute' => Hubzero\Events\Priority::NORMAL
    )
);

Triggering Events

Once listeners and events have been registered, the events can be triggered. The listeners will be called in a queue according to their priority for that Event.

// Triggering the onBeforeRoute Event.
$dispatcher->trigger('onBeforeRoute');

The trigger method not only accepts an event name but can also accept a custom Event object.

// Creating an event called "onBeforeRoute" with a "foo" argument.
$event = new Hubzero\Events\Event('onAfterSomething');
$event->setArgument('foo', 'bar');

$dispatcher->trigger($event);

Arguments or data to be passed to the listener can be specified in an array as a second parameter to the trigger.

// Triggering the onBeforeRoute Event.
$dispatcher->trigger('onBeforeRoute', array($foo, $bar));

In the example above, the two variables $foo and $bar are added as arguments to the event object and passed to the listener. This is functionally equivalent to the following:

// Creating an event called "onBeforeRoute" with a "foo" argument.
$event = new Hubzero\Events\Event('onAfterSomething');
$event->setArgument('foo', $foo);
$event->setArgument('bar', $bar);

$dispatcher->trigger($event);

Stopping Events

In some cases, it may make sense for a listener to prevent any other listeners from being called. That is, the listener needs to be able to tell the dispatcher to stop all propagation of the event to future listeners. This can be accomplished from inside a listener by calling the stop() method on the event:

class SystemListener
{
    public function onBeforeRoute(Event $event)
    {
        // Stopping the Event propagation.
        $event->stop();
    }
}

When stopping the Event propagation, the next listeners in the queue won't be called.

It is possible to detect if an event was stopped by using the isStopped() method which returns a boolean value:

class SystemListener
{
    public function onBeforeRoute(Event $event)
    {
        // Stopping the Event propagation.
        $event->stop();

        if ($event->isStopped())
        {
            //...
        }
    }
}

Last modified: