Symfony 4 was released on November 30th.
Update now to the best Symfony ever!

You are browsing the Symfony 4 documentation, which changes significantly from Symfony 3.x. If your app doesn't use Symfony 4 yet, browse the Symfony 3.4 documentation.

How to Define Commands as Services

How to Define Commands as Services

If you're using the default services.yaml configuration, your command classes are already registered as services. Great! This is the recommended setup.

Note

You can also manually register your command as a service by configuring the service and tagging it with console.command.

In either case, if your class extends ContainerAwareCommand, you can access public services via $this->getContainer()->get('SERVICE_ID').

But if your class is registered as a service, you can instead access services by using normal dependency injection.

For example, suppose you want to log something from within your command:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace App\Command;

use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class SunshineCommand extends Command
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;

        // you *must* call the parent constructor
        parent::__construct();
    }

    protected function configure()
    {
        $this
            ->setName('app:sunshine')
            ->setDescription('Good morning!');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->logger->info('Waking up the sun');
        // ...
    }
}

If you're using the default services.yaml configuration, the command class will automatically be registered as a service and passed the $logger argument (thanks to autowiring). In other words, just by creating this class, everything works! You can call the app:sunshine command and start logging.

Caution

You do have access to services in configure(). However, if your command is not lazy, try to avoid doing any work (e.g. making database queries), as that code will be run, even if you're using the console to execute a different command.

Lazy Loading

To make your command lazily loaded, either define its $defaultName static property:

1
2
3
4
5
6
class SunshineCommand extends Command
{
    protected static $defaultName = 'app:sunshine';

    // ...
}

Or set the command attribute on the console.command tag in your service definition:

  • YAML
    1
    2
    3
    4
    5
    6
    # config/services.yaml
    services:
        App\Command\SunshineCommand:
            tags:
                - { name: 'console.command', command: 'app:sunshine' }
            # ...
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    <!-- config/services.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <services>
            <service id="App\Command\SunshineCommand">
                 <tag name="console.command" command="app:sunshine" />
            </service>
        </services>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    // config/services.php
    use App\Command\SunshineCommand;
    //...
    
    $container
        ->register(SunshineCommand::class)
        ->addTag('console.command', array('command' => 'app:sunshine'))
    ;
    

That's it. One way or another, the SunshineCommand will be instantiated only when the app:sunshine command is actually called.

Note

You don't need to call setName() for configuring the command when it is lazy.

Caution

Calling the list command will instantiate all commands, including lazy commands.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.