Как определять команды, как сервисы

Как определять команды, как сервисы

Если вы используете конфигурацию services.yaml по умолчанию , то ваши классы команд уже зарегистрированы, как сервисы. Отлично! Это рекомендованная установка.

Note

Вы также можете вручную зарегистрировать вашу команду, как сервис, сконфигурировав сервис и тегировав его с помощью console.command.

В любом случае, если ваш класс расширяет ContainerAwareCommand, то вы можете получить доступ к публичным сервисам через $this->getContainer()->get('SERVICE_ID').

Но если ваш класс зарегистрирован, как сервис, вы можете вместо этого получить доступ к сервисам, используя нормальное внедрение зависимости .

Например, представьте, что вы хотите записать лог чего-либо изнутри вашей команды:

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;

        // вы *должны* вызвать родительский конструктор
        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');
        // ...
    }
}

Если вы используете конфигурацию services.yaml по умолчанию , то класс команды автоматически будет зарегистрирован, как сервис, и передан аргументу $logger (благодаря автомонтированию). Другими словами, просто создав этот класс, всё работает! Вы можете вызвать команду app:sunshine и начать вести запись логов.

Caution

У вас есть достут к серверам configure(). Однако, если ваша команда не ленивая , попробуйте избегать любой работы (например, запросы в DB), так как этот код будет выполнен, даже если вы используете консоль для выполнения другой комнады.

Ленивая загрузка

Чтобы сделать вашу команду лениво загружаемой, определите её статичное свойство $defaultName:

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

    // ...
}

Или установите атрибут command в теге console.command в вашем определении сервиса:

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
# config/services.yaml
services:
    App\Command\SunshineCommand:
        tags:
            - { name: 'console.command', command: 'app:sunshine' }
        # ...

Вот и всё. Так или иначе, SunshineCommand будет инстанциирована только тогда, когда команда app:sunshine будет действительно вызвана.

Note

Вам не нужно вызывать setName() для конфигуриации команды, если она ленивая.

Caution

Вызов команды list инстанциирует все команды, включая ленивые.