Today, we're going to learn how to use the Symfony event dispatcher component, which allows you to create events and listeners in your PHP applications. Thus, different components of your application can talk to each other with loosely coupled code.
What Is the Symfony Event Dispatcher Component?
You may be familiar with the event-observer pattern, which allows you to define listeners for system-generated events so that they are executed when the event is triggered. Similarly, the Symfony EventDispatcher component allows you to set up a system in which you could create custom events and listeners. In that way, you allow components in your application to react if something happens in a system.
In fact, the event dispatcher component provides three elements that you could build your app architecture around: event, listener, and dispatcher. The whole system is orchestrated by the dispatcher class, which raises events at appropriate points in an application and calls listeners associated with those events.
Let's assume that you want to allow other components in your application to react when the cache is cleared. In that case, you need to define the clear cache event in the first place. After the cache is cleared, you can use the dispatcher to raise the clear cache event, and that notifies all listeners that are listening to this event. This gives listeners the opportunity to purge component-specific caches.
In this article, we'll explore the basics of the event dispatcher component. We'll start with installation and configuration, and we'll also create a few real-world examples to demonstrate all the concepts mentioned above.
Installing and Configuring the Event Dispatcher
In this section, we're going to install the event dispatcher component. I assume that you've already installed Composer on your system, because we'll need it to install the EventDispatcher component.
Once you've installed Composer, go ahead and install the EventDispatcher component using the following command.
$composer require symfony/event-dispatcher
That should have created the composer.json file, which should look like this:
{ "require": { "symfony/event-dispatcher": "^4.1" } }
Let's further edit the composer.json file to look like the following:
{ "require": { "symfony/event-dispatcher": "^4.1" }, "autoload": { "psr-4": { "EventDispatchers\\": "src" }, "classmap": ["src"] } }
As we've added a new classmap entry, go ahead and update the Composer autoloader by running the following command.
$composer dump -o
Now, you can use the EventDispatchers
namespace to autoload classes under the src directory.
So that's the installation part, but how are you supposed to use it? In fact, it's just a matter of including the autoload.php file created by Composer in your application, as shown in the following snippet.
<?php require_once './vendor/autoload.php'; // application code ?>
How to Create, Dispatch, and Listen to Events
In this section, we'll go through an example which demonstrates how you could create a custom event and set up a listener for that event.
The Event Class
To start with, go ahead and create the src/Events/DemoEvent.php file with the following contents.
<?php namespace EventDispatchers\Events; use Symfony\Component\EventDispatcher\Event; class DemoEvent extends Event { const NAME = 'demo.event'; protected $foo; public function __construct() { $this->foo = 'bar'; } public function getFoo() { return $this->foo; } }
Our custom DemoEvent
class extends the core Event
class of the EventDispatcher component. The NAME
constant holds the name of our custom event—demo.event
. It's used when you want to set up a listener for this event.
The Listener Class
Next, let's create the listener class src/Listeners/DemoListener.php with the following contents.
<?php namespace EventDispatchers\Listeners; use Symfony\Component\EventDispatcher\Event; class DemoListener { public function onDemoEvent(Event $event) { // fetch event information here echo "DemoListener is called!\n"; echo "The value of the foo is: ".$event->getFoo()."\n"; } }
The DemoListener
class implements the onDemoEvent
method which is triggered when the system dispatches the DemoEvent
event. Of course, it won't happen automatically yet, as we need to register the DemoListener
listener to listen the demo.event
event using the EventDispatcher class.
So far, we've created event and listener classes. Next, we'll see how to tie all these pieces together.
An Example File
Let's create the basic_example.php file with the following contents.
<?php // basic_example.php require_once './vendor/autoload.php'; use Symfony\Component\EventDispatcher\EventDispatcher; use EventDispatchers\Events\DemoEvent; use EventDispatchers\Listeners\DemoListener; // init event dispatcher $dispatcher = new EventDispatcher(); // register listener for the 'demo.event' event $listener = new DemoListener(); $dispatcher->addListener('demo.event', array($listener, 'onDemoEvent')); // dispatch $dispatcher->dispatch(DemoEvent::NAME, new DemoEvent());
The EventDispatcher
class is the most important element in the EventDispatcher component—it allows you to bind listeners to events they want to listen to. We've used the addListener
method of the EventDispatcher
class to listen to the demo.event
event.
The first argument of the addListener
method is an event name, and the second argument is the PHP callable which is triggered when the registered event is dispatched. In our case, we've provided the DemoListener
object as a listener along with the onDemoEvent
method.
$dispatcher->addListener('demo.event', array($listener, 'onDemoEvent'));
Finally, we've used the dispatch
method of the EventDispatcher
class to dispatch the demo.event
event.
$dispatcher->dispatch(DemoEvent::NAME, new DemoEvent());
When you run the basic_example.php file, it should produce the following output.
$php basic_example.php DemoListener is called! The value of the foo is: bar
As expected, the onDemoEvent
method of the DemoListener
class is called, and that in turn calls the getFoo
method of the DemoEvent
class to fetch the event-related information.
What Is an Event Subscriber?
In the previous section, we built an example which demonstrated how to create a custom event and a custom listener. We also discussed how to bind a listener to the specific event using the EventDispatcher
class.
That was a simple example, as we only wanted to set up a listener for a single event. On the other hand, if you want to set up listeners for multiple events or you want to logically group event handling logic in a single class, you should consider using event subscribers because they allow you to keep everything in one place.
In this section, we'll revise the example which was created in the previous section.
The Subscriber Class
The first thing that we need to do is to create a subscriber class which implements the EventSubscriberInterface
interface. Go ahead and create the src/Subsribers/DemoSubscriber.php class as shown in the following snippet.
<?php namespace EventDispatchers\Subscribers; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use EventDispatchers\Events\DemoEvent; class DemoSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents() { return array( DemoEvent::NAME => 'onDemoEvent', ); } public function onDemoEvent(DemoEvent $event) { // fetch event information here echo "DemoListener is called!\n"; echo "The value of the foo is :".$event->getFoo()."\n"; } }
Since the class DemoSubscriber
implements the EventSubscriberInterface
interface, it must implement the getSubscribedEvents
method. The getSubscribedEvents
method should return an array of events that you want to subscribe to. You need to provide the event name in an array key and the method name in an array value which is called when the event is triggered.
The last thing is to implement the listener method in the same class. In our case, we need to implement the onDemoEvent
method, and we've already done that.
An Example File
It's time to test our subscriber! Let's quickly create the subscriber_example.php file with the following contents.
<?php require_once './vendor/autoload.php'; use Symfony\Component\EventDispatcher\EventDispatcher; use EventDispatchers\Subscribers\DemoSubscriber; use EventDispatchers\Events\DemoEvent; // init event dispatcher $dispatcher = new EventDispatcher(); // register subscriber $subscriber = new DemoSubscriber(); $dispatcher->addSubscriber($subscriber); // dispatch $dispatcher->dispatch(DemoEvent::NAME, new DemoEvent());
You need to use the addSubscriber
method of the EventDispatcher
class to subscribe your custom subscriber, and the EventDispatcher
class handles the rest. It fetches events to be subscribed from the getSubscribedEvents
method and sets up listeners for those events. Apart from that, everything is the same, and it should work as expected with no surprises.
Let's test it!
$php subscriber_example.php DemoListener is called! The value of the foo is: bar
And that was an event subscriber at your disposal! That also brings us to the end of this article.
Conclusion
Today, we explored the Symfony event dispatcher component, which allows you to set up events and listeners in your PHP applications. By using this library, you can create a loosely coupled system which allows components of your application to communicate with each other effortlessly.
Feel free to share your thoughts and queries using the form below!
No comments:
Post a Comment