<commit_before>.. _tutorials.eventmanager.rst:

Using the EventManager
======================

This tutorial explores the various features of ``Zend\EventManager``.

.. _terminology:

Terminology
-----------

* An **Event** is a named action.
* A **Listener** is any PHP callback that reacts to an *event*.
* An **EventManager** *aggregates* listeners for one or more named events, and
  *triggers* events.

Typically, an *event* will be modeled as an object, containing metadata
surrounding when and how it was triggered, including the event name, what object
triggered the event (the "target"), and what parameters were provided. Events
are *named*, which allows a single *listener* to branch logic based on the
event.

.. _getting-started:

Getting started
---------------

The minimal things necessary to start using events are:

* An ``EventManager`` instance
* One or more listeners on one or more events
* A call to ``trigger()`` an event

The simplest example looks something like this:

.. code-block:: php
    :linenos:

    use Zend\EventManager\EventManager;

    $events = new EventManager();
    $events->attach('do', function ($e) {
        $event = $e->getName();
        $params = $e->getParams();
        printf(
            'Handled event "%s", with parameters %s',
            $event,
            json_encode($params)
        );
    });

    $params = array('foo' => 'bar', 'baz' => 'bat');
    $events->trigger('do', null, $params);

The above will result in the following::

    Handled event "do", with parameters {"foo":"bar","baz":"bat"}

.. note::

    Throughout this tutorial, we use closures as listeners. However, any valid
    PHP callback can be attached as a listeners: PHP function names, static
    class methods, object instance methods, functors, or closures. We use
    closures within this post simply for illustration and simplicity.

If you were paying attention to the example, you will have noted the ``null``
argument. Why is it there?

Typically, you will compose an ``EventManager`` within a class, to allow
triggering actions within methods. The middle argument to ``trigger()`` is the
"target", and in the case described, would be the current object instance. This
gives event listeners access to the calling object, which can often be useful.

.. code-block:: php
    :linenos:

    use Zend\EventManager\EventManager;
    use Zend\EventManager\EventManagerAwareInterface;
    use Zend\EventManager\EventManagerInterface;

    class Example implements EventManagerAwareInterface
    {
        protected $events;
        
        public function setEventManager(EventManagerInterface $events)
        {
            $events->setIdentifiers(array(
                __CLASS__,
                get_class($this)
            ));
            $this->events = $events;
        }
        
        public function getEventManager()
        {
            if (!$this->events) {
                $this->setEventManager(new EventManager());
            }
            return $this->events;
        }
        
        public function do($foo, $baz)
        {
            $params = compact('foo', 'baz');
            $this->getEventManager()->trigger(__FUNCTION__, $this, $params);
        }

    }

    $example = new Example();

    $example->getEventManager()->attach('do', function($e) {
        $event  = $e->getName();
        $target = get_class($e->getTarget()); // "Example"
        $params = $e->getParams();
        printf(
            'Handled event "%s" on target "%s", with parameters %s',
            $event,
            $target,
            json_encode($params)
        );
    });

    $example->do('bar', 'bat');

The above is basically the same as the first example. The main difference is
that we're now using that middle argument in order to pass the target, the
instance of ``Example``, on to the listeners. Our listener is now retrieving
that (``$e->getTarget()``), and doing something with it.

If you're reading this critically, you should have a new question: What is the
call to ``setIdentifiers()`` for?

.. _shared-managers:

Shared managers
---------------

One aspect that the ``EventManager`` implementation provides is an ability to
compose a ``SharedEventManagerInterface`` implementation. 

``Zend\EventManager\\SharedEventManagerInterface`` describes an object that
aggregates listeners for events attached to objects with specific *identifiers*.
It does not trigger events itself. Instead, an ``EventManager`` instance that
composes a ``SharedEventManager`` will query the ``SharedEventManager`` for
listeners on identifiers it's interested in, and trigger those listeners as
well.

How does this work, exactly?

Consider the following:

.. code-block:: php
    :linenos:

    use Zend\EventManager\SharedEventManager;

    $sharedEvents = new SharedEventManager();
    $sharedEvents->attach('Example', 'do', function ($e) {
        $event  = $e->getName();
        $target = get_class($e->getTarget()); // "Example"
        $params = $e->getParams();
        printf(
            'Handled event "%s" on target "%s", with parameters %s',
            $event,
            $target,
            json_encode($params)<commit_msg>Fix typo in SharedEventManagerInterface path<commit_after>.. _tutorials.eventmanager.rst:

Using the EventManager
======================

This tutorial explores the various features of ``Zend\EventManager``.

.. _terminology:

Terminology
-----------

* An **Event** is a named action.
* A **Listener** is any PHP callback that reacts to an *event*.
* An **EventManager** *aggregates* listeners for one or more named events, and
  *triggers* events.

Typically, an *event* will be modeled as an object, containing metadata
surrounding when and how it was triggered, including the event name, what object
triggered the event (the "target"), and what parameters were provided. Events
are *named*, which allows a single *listener* to branch logic based on the
event.

.. _getting-started:

Getting started
---------------

The minimal things necessary to start using events are:

* An ``EventManager`` instance
* One or more listeners on one or more events
* A call to ``trigger()`` an event

The simplest example looks something like this:

.. code-block:: php
    :linenos:

    use Zend\EventManager\EventManager;

    $events = new EventManager();
    $events->attach('do', function ($e) {
        $event = $e->getName();
        $params = $e->getParams();
        printf(
            'Handled event "%s", with parameters %s',
            $event,
            json_encode($params)
        );
    });

    $params = array('foo' => 'bar', 'baz' => 'bat');
    $events->trigger('do', null, $params);

The above will result in the following::

    Handled event "do", with parameters {"foo":"bar","baz":"bat"}

.. note::

    Throughout this tutorial, we use closures as listeners. However, any valid
    PHP callback can be attached as a listeners: PHP function names, static
    class methods, object instance methods, functors, or closures. We use
    closures within this post simply for illustration and simplicity.

If you were paying attention to the example, you will have noted the ``null``
argument. Why is it there?

Typically, you will compose an ``EventManager`` within a class, to allow
triggering actions within methods. The middle argument to ``trigger()`` is the
"target", and in the case described, would be the current object instance. This
gives event listeners access to the calling object, which can often be useful.

.. code-block:: php
    :linenos:

    use Zend\EventManager\EventManager;
    use Zend\EventManager\EventManagerAwareInterface;
    use Zend\EventManager\EventManagerInterface;

    class Example implements EventManagerAwareInterface
    {
        protected $events;
        
        public function setEventManager(EventManagerInterface $events)
        {
            $events->setIdentifiers(array(
                __CLASS__,
                get_class($this)
            ));
            $this->events = $events;
        }
        
        public function getEventManager()
        {
            if (!$this->events) {
                $this->setEventManager(new EventManager());
            }
            return $this->events;
        }
        
        public function do($foo, $baz)
        {
            $params = compact('foo', 'baz');
            $this->getEventManager()->trigger(__FUNCTION__, $this, $params);
        }

    }

    $example = new Example();

    $example->getEventManager()->attach('do', function($e) {
        $event  = $e->getName();
        $target = get_class($e->getTarget()); // "Example"
        $params = $e->getParams();
        printf(
            'Handled event "%s" on target "%s", with parameters %s',
            $event,
            $target,
            json_encode($params)
        );
    });

    $example->do('bar', 'bat');

The above is basically the same as the first example. The main difference is
that we're now using that middle argument in order to pass the target, the
instance of ``Example``, on to the listeners. Our listener is now retrieving
that (``$e->getTarget()``), and doing something with it.

If you're reading this critically, you should have a new question: What is the
call to ``setIdentifiers()`` for?

.. _shared-managers:

Shared managers
---------------

One aspect that the ``EventManager`` implementation provides is an ability to
compose a ``SharedEventManagerInterface`` implementation. 

``Zend\EventManager\SharedEventManagerInterface`` describes an object that
aggregates listeners for events attached to objects with specific *identifiers*.
It does not trigger events itself. Instead, an ``EventManager`` instance that
composes a ``SharedEventManager`` will query the ``SharedEventManager`` for
listeners on identifiers it's interested in, and trigger those listeners as
well.

How does this work, exactly?

Consider the following:

.. code-block:: php
    :linenos:

    use Zend\EventManager\SharedEventManager;

    $sharedEvents = new SharedEventManager();
    $sharedEvents->attach('Example', 'do', function ($e) {
        $event  = $e->getName();
        $target = get_class($e->getTarget()); // "Example"
        $params = $e->getParams();
        printf(
            'Handled event "%s" on target "%s", with parameters %s',
            $event,
            $target,
            json_encode($params)
{'fraction_non_alphanumeric': 0.12045760430686406, 'fraction_numerical': 0.0, 'mean_word_length': 2.8759314456035767, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4328223', 'n_tokens_mistral': 2774, 'n_tokens_neox': 2659, 'n_words': 1053}