A little more advanced ZF2 EventManager usage

<note>I found out that this usage is going to be deprecated.  This feature will remain, but for the GA (and beta 4 most likely) this code may not work.  I will be updating this blog post when that happens</note>

If you look at my previous post on the ZF2 EventManager class you might be tempted to think that you are limited only to listening to events for local instances of the event manager.  But no, my friend, you would be wrong.

The event manager actually provides access to a sort of global event manager.  But it’s more than that.  This global event manager allows you to listen in on events for various targets.

So let’s say that you have an event manager for a given class in a given namespace.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace ns1 {
 
  use Zend\EventManager\EventManager;
 
  class cls1 {
 
    protected $events;
 
    public function __construct()
    {
      $this->events = new EventManager(__CLASS__);
    }
 
    public function execute()
    {
      $this->events->trigger('meesa.triggered', $this);
    }
  }
}

Take a look at the constructor.  What you are doing there is giving the event manager an identifier.  Identifiers are not needed, but if you want to allow other event manager instances to attach to its events an identifier will make it globally known.

Next up we will create a class that attaches to that event manager by calling the StaticEventManager class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace ns2 {
 
  use Zend\EventManager\Event,
  Zend\EventManager\StaticEventManager;
 
  class cls2 {
 
    public function listen(Event $e)
    {
      echo get_class($this) . ' has been called by ' . get_class($e->getTarget());
    }
  }
 
  StaticEventManager::getInstance()->attach('ns1\cls1', 'meesa.triggered', array(new cls2, 'listen'));
}

We’re not calling the class ns1\cls1 in this case, just attaching to its event.  When setting this up we attach to the identifier that we provided in the first class (often a class name), followed by the event name and them providing the  class and method name via a callback.  When the event is triggered that callback will be called and we will we will  print out the target class.

1
2
3
4
use ns1\cls1;
 
$cls = new cls1();
$cls->execute();

When we execute that code we get the following output.

ns2\cls2 has been called by ns1\cls1

So even though ns2\cls2 and ns1\cls1 had virtually no knowledge of each other (we did because we “set them up to succeed”), we were able to call code from across the codebase with great ease.

4 comments
stm
stm

Is that a typo in the results? Should

ns2\cls2 has been called by ns2\cls2

actually be

ns2\cls2 has been called by ns1\cls1

 

 

some more descriptive class names would probably make this example clearer..

kschroeder
kschroeder moderator

 @stm Yeah, you're right.  Even my test output shows that.  Not sure why it came out like that.  Will change.

stm
stm

 @kschroeder Does getTarget get the targeted class, not the triggering class?

kschroeder
kschroeder moderator

 @stm getTarget() provides whatever is stated in the second argument of trigger().  Generally that will be $this, but there are circumstances where a different object can be provided.

Post Navigation

Web Analytics