[Translation] PSR-14 - the main event in PHP

[Translation] PSR-14 - the main event in PHP


Last year PHP-FIG - PHP Compatibility Concepts Group , has released several new specifications. The last one, PSR-14 , is dedicated to event dispatching. Like other PSRs, this is a local specification, but has a great influence on many aspects of standardization.

From the translator: This is the translation of the first part of a series of publications in which Larry (Crell) Garfield, one of the members of PHP-FIG, explains what PSR-14 is, what it can do and what it doesn’t, and what is best use it in your projects.

Target


Event dispatch has long been used in many languages. If you have ever used EventDispatcher in Symfony , the Event system in Laravel , hooks in Drupal, Event Manager in the Zend framework, the package League \ Event , or something like that, then you understand what I mean.

In a general sense, all these systems are a form of "observer-mediator". One code fragment sends a message of the type - “event”, and the intermediary sends it to other separate code fragments - “listeners”. Sometimes the signal is directed only in one direction, sometimes the “listener” can somehow transmit data back to the caller. Of course, they are all different and not very compatible with each other.

This is a problem for standalone libraries that want to connect to different libraries and applications. Many libraries can be expanded by sending events in one form or another, so that other code can link to them. But such an intermediary layer is, in fact, proprietary. The library that runs the symfony eventDispatcher is then merged with symfony. Then using it somewhere else requires installing an EventDispatcher and connecting to libraries in the program. The library that calls the binding system from Drupal module_invoke_all () , then links to Drupal. And so on.

The purpose of PSR-14 is to rid the library of this dependency. This allows libraries to expand through a thin common layer, and then facilitate their transfer to another environment without additional efforts and costs, for example, in Symfony, Zend Framework, Laravel, TYPO3, eZ Platform or Slim. As long as the environment has compatibility with PSR-14, everything will work.

Specification


As already mentioned, the specification is quite easy. These are three interfaces in one method and a meta description of how to use them. Everything is simple and convenient. Below is the code of these interfaces (no comments to save space).

  namespace Psr \ EventDispatcher;

 interface EventDispatcherInterface
 {
  public function dispatch (object $ event);
 }

 interface ListenerProviderInterface
 {
  public function getListenersForEvent (object $ event): iterable;
 }

 interface StoppableEventInterface
 {
  public function isPropagationStopped (): bool;
 }  

The first two are the core specifications. StoppableEventInterface is an extension, which we will return to later.

I think EventDispatcher is familiar to most of you - this is just an object with a method to which you transmit the event - the mediator, which you have already talked about. The event itself, however, is undefined - it can be any PHP object . More on this later.

Most existing implementations have one object or set of functions that act as an intermediary or dispatcher and a place to register the code that receives the event (listeners). For PSR-14, we consciously divided these two responsibilities into separate objects. The dispatcher receives a list of listeners from the supplier object that makes this list.

Where does the provider get the list of listeners then? Yes, where he wants from! There is a billion and one ways to connect the listener and the event, they are all absolutely valid and incompatible. At the beginning, we decided that the standardization of the “One True Way” of registering listeners would be too limited. However, by standardizing the process of connecting the listener to the dispatcher, you can get excellent flexibility without forcing the user to do something strange and incomprehensible.

Also, the code does not indicate what the listener is. It can be any PHP-capable fragment of a signal: a function, an anonymous function, an object method, anything. Since the callee can do anything, it means that it is acceptable to have as a listener, say, an anonymous function that performs a deferred loading of the service from the DI container and calls the service method, which actually contains the listening code.

In short, a dispatcher is a simple and easy API for library authors. Listener vendors offer a robust and flexible API for framework integrators, and the relationship between the controller and the provider brings them together.

A simple example


In general terms, the scheme of combining all the parts into a whole will look something like this.

  class Dispatcher implements EventDispatcherInterface
 {

  public function __construct (ListenerProviderInterface $ provider)
  {
  $ this- & gt; provider = $ provider;
  }

  public function dispatch (object $ event)
  {
  foreach ($ this- & gt; provider- & gt; getListenersForEvent ($ event) as $ listener) {
  $ listener ($ event);
  }
  return $ event;
  }
 }

 $ dispatcher = new Dispatcher ($ provider);

 $ event = new SomethingHappened ();
 $ dispatcher- & gt; dispatch ($ event);
  

This small piece of code opens up great possibilities, and it is very flexible. In the following articles we will talk in detail about its properties, analyze some structural solutions and consider the sets of ways to use such lightweight events.

Code


PSR-14 is already supported by main frameworks and applications.

  • Matthew Weier O’Phinney has already pledged to introduce PSR-14 support in zend-eventmanager 4.0 in the Zend framework.
  • Symfony recently announced changes to the EventDispatcher for compatibility with PSR- 14, which will give full support in 5.0/5.1.
  • The framework Yii announced its intention to integrate PSR-14 in version 3.0 .
  • Benni Mack from TYPO3 CMS said that in the next release of TYPO3, all existing “trap + signal/slot” concepts will support PSR-14.

The PSR-14 also has three fully functional, independent implementations that you can already use in any application.


The author thanks the entire working group of PSR: Larry Garfield , Cees-Jan Kiewiet , Benjamin Mack , Elizabeth Smith , Ryan Weaver , Matthew Weier O'Phinney . Throughout the work, the process was highly productive: everyone worked together, collectively, as it should be. The result is good, and we would like all further efforts in joint work on the architecture to be just as productive.

You can learn more details from the original of the following parts and documentation or May 17th at PHP Russia . The second option is attractive for several reasons. For example, the head of the Program Committee, Alexander ( samdark ) Makarov is among those who implemented PSR-14 in Yii. And in principle, the composition of the Program Committee and speakers is incredibly strong, there is hardly any topic from the sphere of professional use of PHP that cannot be discussed at this conference.

Source text: [Translation] PSR-14 - the main event in PHP