Использование событий
Дата обновления перевода 2023-01-20
Использование событий
Класс Application компонента Console позволяет вам по желанию подключаться к жизненному циклу консольного приложения через события. Вместо того, чтобы изобретать велосипед, он использует компонент Symfony EventDispatcher, чтобы сделать работу:
1 2 3 4 5 6 7 8
use Symfony\Component\Console\Application;
use Symfony\Component\EventDispatcher\EventDispatcher;
$dispatcher = new EventDispatcher();
$application = new Application();
$application->setDispatcher($dispatcher);
$application->run();
Caution
События консоли вызываются только путём выполнения основной команды. Команды, вызванные основной командой, не запустят ни одно событие.
Событие ConsoleEvents::COMMAND
Типичное назначение: Сделать что-либо до запуска любой команды (вроде логирования, какая команда будет выполнена), или отобразить что-то о том событии, которое будет выполнено.
Событие ConsoleEvents::COMMAND
запускается прямо перед вызовом любой
команды. Слушатели получают событие
ConsoleCommandEvent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
$dispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
// получает экземпляр ввода
$input = $event->getInput();
// получает экземпляр вывода
$output = $event->getOutput();
// получает команду, которая будет выполнена
$command = $event->getCommand();
// пишет что-то о команде
$output->writeln(sprintf('Before running command <info>%s</info>', $command->getName()));
// получает приложение
$application = $command->getApplication();
});
Отключение команд внутри слушателей
Используя метод
disableCommand(),
вы можете отключать команды внутри слушателя. Тогда приложение не будет выполнять
команду, а вместо этого вернёт код 113
(определённый в
ConsoleCommandEvent::RETURN_CODE_DISABLED
). Этот код является одним из
зарезервированных кодов завершения для команд консоль, которые подчиняются
стандарту C/C++.:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
$dispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
// получает команду, которая будет выполнена
$command = $event->getCommand();
// ... проверить, можно ли выполнить команду
// отключает команду, что приведёт к пропуску команды
// и возвращению кода 113 из приложения
$event->disableCommand();
// возможно включить команду в более позднем слушателе
if (!$event->commandShouldRun()) {
$event->enableCommand();
}
});
Событие ConsoleEvents::ERROR
Типичное назначение: Обрабатывать исключения, вызванные во время выполнения команды.
Каждый раз, когда команда вызывает исключение, включая те, что запускаются
из слушателей событий, выполняется событиеConsoleEvents::ERROR
. Слушатель
может обернуть или изменить исключение или сделать что-либо полезное перед тем,
как приложение вызовет исключение.
Слушатели получают событие ConsoleErrorEvent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
use Symfony\Component\Console\Event\ConsoleErrorEvent;
use Symfony\Component\Console\Event\ConsoleErrorEvent;
$dispatcher->addListener(ConsoleEvents::ERROR, function (ConsoleErrorEvent $event) {
$output = $event->getOutput();
$command = $event->getCommand();
$output->writeln(sprintf('Oops, exception thrown while running command <info>%s</info>', $command->getName()));
// получает текущий код завершения (код исключения)
$exitCode = $event->getExitCode();
// меняет исключение на другое
$event->setException(new \LogicException('Caught exception', $exitCode, $event->getError()));
});
Событие ConsoleEvents::TERMINATE
Типичное назначение: Выполнит некоторые очищающие действия после выполнения команды.
После выполнени команды, вызывается событие ConsoleEvents::TERMINATE
. Оно может
быть использовано для выполнения любых действий, необходимых для всех команд, или
для уборки того, что вы начали в слушателе ConsoleEvents::COMMAND
(вроде отправки
логов, закрытия соединения DB, отправки электронных писем, ...). Слушатель также
может изменить код завершения.
Слушатели получают событие ConsoleTerminateEvent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
$dispatcher->addListener(ConsoleEvents::TERMINATE, function (ConsoleTerminateEvent $event) {
// получает вывод
$output = $event->getOutput();
// получает выполненную команду
$command = $event->getCommand();
// отображает заданное содержание
$output->writeln(sprintf('After running command <info>%s</info>', $command->getName()));
// изменяет код завершения
$event->setExitCode(128);
});
Tip
Это событие также выполняется когда команда вызывает исключение. Тогда оно
выполняется прямо после события ConsoleEvents::ERROR
. В этом случае,
полученный код завершения является кодом исключения.
Событие ConsoleEvents::SIGNAL
Типичное назначение*: Для выполнения некоторых действий после прерывания выполнения команды.
Сигналы - это асинхронные уведомления, отправленные процессу для того, чтобы
уведоить его о произошедшем событии. Например, когда вы нажимаете Ctrl + C
в
команде, операционная система отправляет ей сигнал SIGINT
.
Когда команда прерывается, Symfony запускает событие ConsoleEvents::SIGNAL
.
Слушайте это событие, чтобы вы могли выполнить какие-то действия (например, ведение
логов каких-то результатов, очистку некоторых временных файлов и т.д.) до завершения
выполнения команды.
Слушатели получают событие ConsoleSignalEvent:
1 2 3 4 5 6 7 8 9 10 11 12
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleSignalEvent;
$dispatcher->addListener(ConsoleEvents::SIGNAL, function (ConsoleSignalEvent $event) {
// получает число сигнала
$signal = $event->getHandlingSignal();
if (\SIGINT === $signal) {
echo "bye bye!";
}
});
Tip
Все доступные сигналы (SIGINT
, SIGQUIT
, и др.) определены как
константы PHP-расширения PCNTL.
Если вы используете компонент Консоль внутри приложения Symfony, команды могут обрабатывать сигналы самостоятельно. Чтобы сделать это, реализуйте SignalableCommandInterface, и подпишитесь на один или более сигналов:
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
// src/Command/SomeCommand.php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\SignalableCommandInterface;
class SomeCommand extends Command implements SignalableCommandInterface
{
// ...
public function getSubscribedSignals(): array
{
// здесь верните любое содержание, определенное расширением PCNTL
return [\SIGINT, \SIGTERM];
}
public function handleSignal(int $signal)
{
if (\SIGINT === $signal) {
// ...
}
// ...
}
}