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

Дата обновления перевода 2024-07-16

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

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

Note

Вы также можете вручную зарегистрировать вашу команду, как сервис, сконфигурировав сервис и тегировав его с помощью console.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\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(name: 'app:sunshine')]
class SunshineCommand extends Command
{
    public function __construct(
        private LoggerInterface $logger,
    ) {
        // вы *должны* вызвать родительский конструктор
        parent::__construct();
    }

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

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

        return Command::SUCCESS;
    }
}

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

Caution

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

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

Чтобы команда загружалась лениво, либо определите ее имя с помощью атрибута PHP AsCommand:

1
2
3
4
5
6
7
8
use Symfony\Component\Console\Attribute\AsCommand;
// ...

#[AsCommand(name: 'app:sunshine')]
class SunshineCommand extends Command
{
    // ...
}

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

1
2
3
4
5
6
7
# config/services.yaml
services:
    # ...

    App\Command\SunshineCommand:
        tags:
            - { name: 'console.command', command: 'app:sunshine' }

Note

Если в команде определены псевдонимы (с помощью метода getAliases()), необходимо добавить по одному тегу console.command на каждый псевдоним.

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

Note

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

Caution

Вызов команды list инстанциирует все команды, включая ленивые. Однако если команда является Symfony\Component\Console\Command\LazyCommand, то
базовая фабрика команд не будет выполнена.