Фремворк Symfony предоставляет множество консольных команд через скрипт bin/console (например, хорошо известная всем команда для очистки кеша bin/console cache:clear). Эти команды создаются с помощью компонента Console. Вы также можете использовать его для создания своих собственных команд.
Консоль: APP_ENV и APP_DEBUG
Консольные команды выполняются в окружении, определенном в переменной APP_ENV файла .env, по умолчанию установлено значение dev. Также читается значение переменной APP_DEBUG, чтобы включать или отключать режим «отладки» (по умолчанию установлено 1, что значит режим отладки включен).
Чтобы запустить консольную команду в другом окружении или в другом режиме отладки, измените значения переменных APP_ENV и APP_DEBUG.
Создание консольных команд
Консольные команды определяются в классах, расширяющих базовый класс Command. Например, вы можете захотеть команду для создания пользователя:
Конфигурация команд
Первое, что следует сделать, это дать описание новой консольной команды в методе configure(). Затем вы можете опционально определить сообщение для справки о команде, а также установить входные параметры и аргументы:
// ...
protected function configure()
{
$this
// краткое описание команды, отображаемое при запуске "php bin / console list"
->setDescription('Creates a new user.')
// полное описание команды, отображаемое при запуске команды с параметром --help
->setHelp('This command allows you to create a user...')
;
}
Метод configure() вызывается автоматически в конце конструктора команд. Если ваша команда определяет свой собственный конструктор, сначала установите свойства, а затем вызовите родительский конструктор, чтобы эти свойства были доступны в методе configure():
requirePassword = $requirePassword;
parent::__construct();
}
public function configure()
{
$this
// ...
->addArgument('password', $this->requirePassword ? InputArgument::REQUIRED : InputArgument::OPTIONAL, 'User password')
;
}
}
Регистрация консольных команд
Консольные команды в Symfony 4 должны быть зарегистрированы как Сервисы и помечены тегом console.command. Если вы используете конфигурацию в файле services.yaml по умолчанию, это уже сделано для вас, благодаря автоконфигурации.
Выполнение (запуск) команд
После конфигурирования и регистрации команды вы можете выполнить ее в терминале:
php bin/console app:create-user
Разумеется сейчас, эта команда ничего не сделает, так как вы еще не написали никакой логики. Добавлять свою собственную логику следует в методе execute ().
Вывод информации в консоль
Метод execute() имеет доступ к потоку вывода для записи сообщений в консоль:
// ...
protected function execute(InputInterface $input, OutputInterface $output)
{
// выводит в консоль несколько строк (добавляя "\n" в конце каждой строки)
$output->writeln([
'User Creator',
'============',
'',
]);
// значение, возвращаемое методом someMethod(), может быть итератором (https://secure.php.net/iterator),
// который генерирует и возвращает сообщения с PHP-ключом "yield"
$output->writeln($this->someMethod());
// выводит сообщение, сопровождаемое "\n" (с новой строки)
$output->writeln('Whoa!');
// выводит сообщение без добавления "\n" к концу строки
// (строки будут выводиться одна за другой)
$output->write('You are about to ');
$output->write('create a user.');
}
Если сейчас выполнить, эту консольную команду, то выведет:
php bin/console app:create-user
User Creator
============
Whoa!
You are about to create a user.
Секции вывода
Стандартный вывод консоли можно разделить на несколько независимых областей, называемых «секции вывода». Создайте один или несколько из таких секций, когда вам нужно очистить и перезаписать выходную информацию.
Секции создаются с помощью метода section(), который возвращает экземпляр ConsoleSectionOutput:
//..........
class MyCommand extends Command
{
//.........
protected function execute(InputInterface $input, OutputInterface $output)
{
$section1 = $output->section();
$section2 = $output->section();
$section1->writeln('Hello');
$section2->writeln('World!');
// вывод отображает "Hello\nWorld!\n"
// метод overwrite() заменяет всё содержимое указанной секции новым указанным текстом
$section1->overwrite('Goodbye');
// теперь будет вывод "Goodbye\nWorld!\n"
// метод clear() удаляет весь контент, указанной секции
$section2->clear();
// Теперь будет вывод "Goodbye\n"
// ...но вы можете указать сколько строк в секции удалить
// (пример ниже удаляет 2 последних строки у указанной секции)
$section1->clear(2);
// Вывод консоли теперь пустой!
}
}
Новая строка добавляется автоматически при отображении информации в секции.
Секции вывода позволяют управлять выводом в консоль расширенными способами, такими как отображение нескольких прогресс-баров выполнения, которые обновляются независимо, и добавление строк в таблицы, которые уже были отрисованы.
Ввод информации в консоль
Используйте входные параметры или аргументы для передачи информации в консольную команду:
//......
use Symfony\Component\Console\Input\InputArgument;
// ...
protected function configure()
{
$this
// конфигурация аргумента
->addArgument('username', InputArgument::REQUIRED, 'The username of the user.')
// ...
;
}
// ...
public function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln([
'User Creator',
'============',
'',
]);
// получение значение входного аргумента, используя метод getArgument()
$output->writeln('Username: '.$input->getArgument('username'));
}
Теперь вы можете передать имя пользователя в консольную команду, добавив его как агрумент, в конце команды:
php bin/console app:create-user Wouter
User Creator
============
Username: Wouter
Для получения дополнительной информации о входных параметрах и аргументах консоли, прочитайте статью консоль ввода (аргументы и параметры).
Получение Сервисов из Сервис-Контейнера.
На практике, чтобы создать нового пользователя, консольная команда в Symfony 4 должна получить доступ к различным Сервисам. Поскольку ваша команда уже зарегистрирована как сервис, вы можете использовать обычную инъекцию зависимостей. Представьте, что у вас есть сервис App\Service\UserManager, к которой вы хотите получить доступ:
// …
use Symfony\Component\Console\Command\Command;
use App\Service\UserManager;
class CreateUserCommand extends Command
{
private $userManager;
public function __construct(UserManager $userManager)
{
$this->userManager = $userManager;
parent::__construct();
}
// …
protected function execute(InputInterface $input, OutputInterface $output)
{
// …
$this->userManager->create($input->getArgument(‘username’));
$output->writeln(‘User successfully generated!’);
}
}
Жизненный цикл консольной команды
Консольные команды в Symfony имеют три метода жизненного цикла, которые вызываются при запуске команды:
- initialize() (необязательный). Этот метод выполняется перед методами interact() и the execute(). Его основная цель — инициализировать переменные, используемые в остальных методах консольной команды.
- interact() (необязательный). Этот метод выполняется после initialize() и перед execute(). Его цель — проверить, отсутствуют ли какие-либо параметры/аргументы, и в интерактивном режиме запросить у пользователя эти значения. Это последнее место, где вы можете запросить отсутствующие параметры/аргументы. После этой команды пропущенные параметры/аргументы приведут к ошибке.
- execute() (обязательный). Этот метод выполняется после выполнения interact() и initialize (). Он содержит логику, которую вы хотите выполнять в консольной команде.
Тестирование консольных команд
Symfony предоставляет несколько инструментов, помогающие вам тестировать ваши консольные команды. Наиболее полезным является класс CommandTester. Он использует специальные классы ввода и вывода для облегчения тестирования без реальной консоли:
find('app:create-user');
$commandTester = new CommandTester($command);
$commandTester->execute([
'command' => $command->getName(),
// передача аргументов хелперу
'username' => 'Wouter',
// при передаче параметров ставим перед ключом две черточки,
// например: '--some-option' => 'option_value',
]);
// вывод результата работы команды в консоль
$output = $commandTester->getDisplay();
$this->assertContains('Username: Wouter', $output);
// ...
}
}
Вы также можете протестировать целое консольное приложение с помощью ApplicationTester.
При использовании компонента Console в автономном проекте используйте Symfony\Component\Console\Application и расширьте обычный \PHPUnit\Framework\TestCase.
Логирование ошибок консольных команд
Всякий раз, когда возникает исключение во время выполнения консольных команд, Symfony добавляет для него сообщение в лог, включая всю неудачную команду. Кроме того, Symfony регистрирует подписчика на событие для прослушивания события ConsoleEvents::TERMINATE и добавляет сообщение в лог, когда команда не завершает работу со статусом выхода 0.