Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Event-Listener best-practice implementation

I am trying to create a CMS-like system in PHP. making it as modular and extendable as possible.

Could someone offer me the best-practice scenario of creating a event-listener system in PHP (a very simplified version of Drupal system for example), creating hooks and implementing them in a short example would also be nice.

like image 711
Y.H. Avatar asked Dec 17 '10 14:12

Y.H.


People also ask

Is there an event listener in PHP?

Listener - A Listener is any PHP callable that expects to be passed an Event. Zero or more Listeners may be passed the same Event. A Listener MAY enqueue some other asynchronous behavior if it so chooses. Emitter - An Emitter is any arbitrary code that wishes to dispatch an Event.

Which is the correct method to add an event listener?

The addEventListener() method allows you to add event listeners on any HTML DOM object such as HTML elements, the HTML document, the window object, or other objects that support events, like the xmlHttpRequest object.

What is the difference between an event handler and an event listener?

Note: Event handlers are sometimes called event listeners — they are pretty much interchangeable for our purposes, although strictly speaking, they work together. The listener listens out for the event happening, and the handler is the code that is run in response to it happening.


2 Answers

Well, there's really three different ways of doing this from an implementation perspective (note that these are OO design patterns, but you could implement them functionally or procedurally if you wanted to).

1. Observer Pattern

You can implement the Observer Pattern. Basically, you'd have each thing that can raise events be a subject. Then the classes/code you want to listen binds to what it wants to listen to specifically. So let's say you have a controller called Foo. If you wanted to listen to it, you could call $fooController->attach($observer);. Then, whenever the controller wanted to say something, it would dispatch the event to all of the observers.

This is really well suited for a notification system (to extend what classes are doing). It's not as well suited for modifying the behavior of code in real time.

2. Decorator Pattern You can also implement the Decorator Pattern. Basically, you take the object that you want to modify, and "wrap" it in a new object that does what you want to change. This is really well suited for modifying and extending the behavior (since you can selectively override functionality from the wrapped class).

This works very well if you have defined interfaces and expect objects to conform to them. If you don't have interfaces (or don't use them properly), most of what the decorator pattern can do for you will be lost.

Also note that this really isn't a way of doing events, it's a way of modifying object behavior.

3. Mediator Pattern

You could also use a Mediator. Basically, you'd have one global mediator that keeps track of your listeners. When you want to trigger an event, you send the event to the mediator. The mediator can then keep track of which listening objects want to receive that event, and pass the message along properly.

This has the advantage of being central. Meaning multiple senders can send the same event, and to the listeners it doesn't make a difference who sent it...

I expanded on this topic in a blog post.

like image 124
ircmaxell Avatar answered Sep 22 '22 22:09

ircmaxell


/*  Example 1:   event::bind('blog.post.create', function($args = array())  {     mail('[email protected]', 'Blog Post Published', $args['name'] . ' has been published'); });   Example 2:   event::trigger('blog.post.create', $postInfo); */  class event {     public static $events = array();      public static function trigger($event, $args = array())     {         if(isset(self::$events[$event]))         {             foreach(self::$events[$event] as $func)             {                 call_user_func($func, $args);             }         }      }      public static function bind($event, Closure $func)     {         self::$events[$event][] = $func;     } } 
like image 40
Codebeat Avatar answered Sep 22 '22 22:09

Codebeat