Events

The symfony/console component allows attaching an event dispatcher instance to a console application. During the lifetime of a console command, the application will trigger a number of events, to which you may subscribe listeners. Internally, laminas/laminas-cli itself adds a listener on the Symfony\Component\Console\ConsoleEvents::TERMINATE event in order to provide command chains.

If you wish to subscribe to any of the various symfony/console events, you will need to provide an alternate event dispatcher instance. You may do so by defining a Laminas\Cli\SymfonyEventDispatcher service in your container that resolves to a Symfony\Component\EventDispatcher\EventDispatcherInterface instance. (We use this instead of the more generic Symfony\Contracts\EventDispatcher\EventDispatcherInterface so that we can use its addSubscriber() method to subscribe our own listener.) Listeners that are callable can be attached using the addListener() method.

As an example, let's say you want to register the Symfony\Component\Console\EventListener\ErrorListener in your console application for purposes of debugging. First, we will create a factory for this listener in the file src/App/ConsoleErrorListenerFactory.php:

<?php

declare(strict_types=1);

namespace App;

use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventListener\ErrorListener;

final class ConsoleErrorListenerFactory
{
    public function __invoke(ContainerInterface $container): ErrorListener
    {
        return new ErrorListener($container->get(LoggerInterface::class));
    }
}

The above example assumes you have already wired the Psr\Log\LoggerInterface service in your container configuration.

Next, we will create the class App\ConsoleEventDispatcherFactory in the file src/App/ConsoleEventDispatcherFactory.php. The factory will create an EventDispatcher instance, attach the error listener, and return the dispatcher.

<?php

declare(strict_types=1);

namespace App;

use Psr\Container\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventListener\ErrorListener;

final class ConsoleEventDispatcherFactory
{
    public function __invoke(ContainerInterface $container): EventDispatcher
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addSubscriber($container->get(ErrorListener::class));

        return $dispatcher;
    }
}

Finally, we need to wire both our ErrorListener and our EventDispatcher services in our container. We can do so by creating a configuration file named config/autoload/console.global.php if it does not already exist, and adding the following contents:

<?php

return [
    '{CONTAINER_KEY}' => [
        'factories' => [
            'Laminas\Cli\SymfonyEventDispatcher' => \App\ConsoleEventDispatcherFactory::class,
            \Symfony\Component\EventDispatcher\EventListener\ErrorListener::class => \App\ConsoleErrorListenerFactory::class,
            // ...
        ],
        // ...
    ],
    // ...
];

For the value of {CONTAINER_KEY}, substitute the following:

  • For laminas-mvc applications, use the value "service_manager".
  • For Mezzio applications, use the value "dependencies".

Later, if you want to register other listeners, you can either update your App\ConsoleEventDispatcherFactory, or you can add delegator factories on the "Laminas\Cli\SymfonyEventDispatcher" service.

Read the symfony/console events documentation more information on how to add listeners to the event dispatcher.