Symfony Console with Dependency Injection

Submitted by timmillwood on Sun, 29/10/2017 - 17:25

Symfony Console is a great component for building a command-line tools. It's bundled as part of the Symfony framework and most of the documentation is geared towards using it with Symfony framework for building commands for recurring jobs.

When building a standalone tool Symfony console can be used by just instantiating the Symfony\Component\Console\Application and passing in a Command object to the add() method. This can quickly result in a monolithic application without the joy of dependency injection. When working with Symfony Framework, console commands can just be created as services with a the tag console.command and they will automatically get added, this does not happen when creating a standalone application.

$container = new ContainerBuilder();
$loader = new YamlFileLoader($container, new FileLocator(__DIR__));
$loader->load('services.yml');
$container->addCompilerPass(new AddConsoleCommandPass);
$container->compile();
$application = new Application();
foreach ($container->getParameter('console.command.ids') as $id) {
  $application->add($container->get($id));
}
$application->run();

In the example above there are three Symfony components in use, Console, Dependency Injection, and Yaml. First the ContainerBuilder is instantiated, and passed to YamlFileLoader from the Yaml component. Using this, the services.yaml file is loaded, which lists all of the services, the ones which are console commands will have the line tags: [console.command]. The AddConsoleCommandPass class from the Console component is instantiated and passed to the container's addCompilerPass method so that all services tagged with the console tag are added to the console.command.ids parameter. This parameter is looped through passing all of the console services to console application class's add method, before running the application.

Once you know how it seems quite simple, and obvious how to use dependency injection to load console command, however this is normally hidden away within the Symfony framework, and doesn't seem to be documented anywhere on the component pages.

Add new comment