PSR-14 - the main event in PHP
- Transfer
Last year, PHP-FIG , the PHP Compatibility Concepts Group, 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 big impact on many aspects of standardization.
From a 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 is capable of and what it is not, and what is the best way to use it in their projects.
Event dispatching has long been used in many languages. If you have ever used EventDispatcher in Symfony , Event system in Laravel , hooks in Drupal, Event Manager in the Zend framework, League \ Event package , or something like that, then you understand what this is about.
In a general sense, all these systems are a form of a “mediator-observer”. One piece of code sends a message of the type - "event", and the intermediary sends it to other individual pieces of code - "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 various libraries and applications. Many libraries can be expanded by sending events in one form or another, so that other code can contact them. But such an intermediary layer is, in fact, proprietary. The library that runs the Symfony EventDispatcher is then combined with Symfony. Then using it somewhere else requires installing EventDispatcher and connecting to the libraries in the program. The library that calls the binding system from Drupal
The goal of PSR-14 is to rid the libraries of this dependency. This allows libraries to expand through a thin common layer, and then facilitate their transfer to another environment without additional effort and expense, for example, in Symfony, Zend Framework, Laravel, TYPO3, eZ Platform or Slim. As long as the environment has compatibility with the PSR-14, everything will work.
As already mentioned, the specification is quite light. 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 for these interfaces (no comment to save space).
The first two are the core of the specification.
I think
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 deliberately divided these two responsibilities into separate objects. The dispatcher receives a list of listeners from the provider object that makes up this list.
Where does the provider get the list of listeners from? Yes, where does he want! There is a billion and one way to connect the listener and the event, all of them are absolutely valid and incompatible. At the beginning, we decided that the standardization of the “One True Way” for registering students 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 fragment capable of signal perception: a function, an anonymous function, an object method, anything. Since the called object can do anything, it is permissible to have, as a listener, an anonymous function, which performs delayed loading of a service from a DI container and calls the method in the service, which actually contains the listening code.
In short, the dispatcher is a simple and easy API for library authors. Listener providers offer a robust and flexible API for framework integrators, and the relationship between the dispatcher and the provider brings them together.
In general terms, the scheme of combining all parts into a whole will look something like this.
This small piece of code offers great opportunities, and it is very flexible. In the following articles, we will talk in detail about its properties, analyze some structural solutions and consider the many ways to use such lightweight events.
PSR-14 is already supported by major frameworks and applications.
PSR-14 also has three fully functional independent implementations that you can already use in any application.
The author thanks the entire PSR working group: Larry Garfield , Cees-Jan Kiewiet , Benjamin Mack , Elizabeth Smith , Ryan Weaver , Matthew Weier O'Phinney . Throughout the work, the process was extremely productive: everyone worked together, collectively, as it should be. The result is pleasing, and I would like all further efforts in joint work on architecture to be as productive.
From a 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 is capable of and what it is not, and what is the best way to use it in their projects.
purpose
Event dispatching has long been used in many languages. If you have ever used EventDispatcher in Symfony , Event system in Laravel , hooks in Drupal, Event Manager in the Zend framework, League \ Event package , or something like that, then you understand what this is about.
In a general sense, all these systems are a form of a “mediator-observer”. One piece of code sends a message of the type - "event", and the intermediary sends it to other individual pieces of code - "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 various libraries and applications. Many libraries can be expanded by sending events in one form or another, so that other code can contact them. But such an intermediary layer is, in fact, proprietary. The library that runs the Symfony EventDispatcher is then combined with Symfony. Then using it somewhere else requires installing EventDispatcher and connecting to the libraries in the program. The library that calls the binding system from Drupal
module_invoke_all()
is then linked to Drupal. And so on.The goal of PSR-14 is to rid the libraries of this dependency. This allows libraries to expand through a thin common layer, and then facilitate their transfer to another environment without additional effort and expense, for example, in Symfony, Zend Framework, Laravel, TYPO3, eZ Platform or Slim. As long as the environment has compatibility with the PSR-14, everything will work.
Specification
As already mentioned, the specification is quite light. 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 for these interfaces (no comment to save space).
namespacePsr\EventDispatcher;
interfaceEventDispatcherInterface{
publicfunctiondispatch(object $event);
}
interfaceListenerProviderInterface{
publicfunctiongetListenersForEvent(object $event) : iterable;
}
interfaceStoppableEventInterface{
publicfunctionisPropagationStopped() : bool;
}
The first two are the core of the specification.
StoppableEventInterface
- This is an extension to which we will return later. I think
EventDispatcher
most of you are familiar with this - it’s just an object with the method to which you pass the event - the intermediary that you already spoke about. The event itself, however, is not defined - 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 deliberately divided these two responsibilities into separate objects. The dispatcher receives a list of listeners from the provider object that makes up this list.
Where does the provider get the list of listeners from? Yes, where does he want! There is a billion and one way to connect the listener and the event, all of them are absolutely valid and incompatible. At the beginning, we decided that the standardization of the “One True Way” for registering students 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 fragment capable of signal perception: a function, an anonymous function, an object method, anything. Since the called object can do anything, it is permissible to have, as a listener, an anonymous function, which performs delayed loading of a service from a DI container and calls the method in the service, which actually contains the listening code.
In short, the dispatcher is a simple and easy API for library authors. Listener providers offer a robust and flexible API for framework integrators, and the relationship between the dispatcher and the provider brings them together.
Simple example
In general terms, the scheme of combining all parts into a whole will look something like this.
classDispatcherimplementsEventDispatcherInterface{
publicfunction__construct(ListenerProviderInterface $provider){
$this->provider = $provider;
}
publicfunctiondispatch(object $event){
foreach ($this->provider->getListenersForEvent($event) as $listener) {
$listener($event);
}
return $event;
}
}
$dispatcher = new Dispatcher($provider);
$event = new SomethingHappened();
$dispatcher->dispatch($event);
This small piece of code offers great opportunities, and it is very flexible. In the following articles, we will talk in detail about its properties, analyze some structural solutions and consider the many ways to use such lightweight events.
Code
PSR-14 is already supported by major frameworks and applications.
- Matthew Weier O'Phinney has already pledged to introduce support for PSR-14 in zend-eventmanager 4.0 in the Zend framework.
- Symfony recently announced changes to EventDispatcher for compatibility with PSR-14, which will give full support in 5.0 / 5.1.
- The Yii framework has announced its intention to integrate the PSR-14 in version 3.0 .
- Benni Mack of TYPO3 CMS said that in the next TYPO3 release, all existing trap + signal / slot concepts will support the PSR-14.
PSR-14 also has three fully functional independent implementations that you can already use in any application.
- Tukio by Larry Garfield, author of this article.
- Phly Event Dispatcher by Matthew Weier O'Phinney.
- Kart from Benni Mack, which works as an embedded plugin.
The author thanks the entire PSR working group: Larry Garfield , Cees-Jan Kiewiet , Benjamin Mack , Elizabeth Smith , Ryan Weaver , Matthew Weier O'Phinney . Throughout the work, the process was extremely productive: everyone worked together, collectively, as it should be. The result is pleasing, and I would like all further efforts in joint work on architecture to be as productive.
You can find out more details either from the original of the next part and the documentation or May 17 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 introduced the 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.