Команды консоли
Дата обновления перевода 2024-07-29
Команды консоли
Фреймворк Symfony предоставляет множество команд через скрипт bin/console
(например, хорошо известная команда bin/console cache:clear
). Эти команды
создаются с помощью Компонента Console. Вы можете
также использовать его для создания собственных команд.
Выполнение команд
Каждое приложение Symfony поставляется с огромным набором команд. Вы можете
использовать команду list
, чтобы увидеть все доступные команды приложения:
1 2 3 4 5 6 7 8 9 10 11 12 13
$ php bin/console list
...
Доступные команды:
about Отобразить информацию о текущем проекте
completion Сбросить скрипт заполнения оболочки
help Отобразить помощь для команды
list Перечислить команды
ресурсы
assets:install Установить веб-ресурсы пакета в публичном каталоге
кеш
cache:clear Очистить кеш
...
Note
list
- это команда по умолчанию, поэтому запуск php bin/console
- это то же самое.
Если вы найдёте команду, которая вам нужна, вы можете запустить её с опцией --help
,
чтобы просмотреть документацию команды:
1
$ php bin/console assets:install --help
Note
--help
- это одна из встроенных глобальных опций компонента Console,
которые доступны для всех команд, включая те, которые вы можете создать.
Чтобы узнать о них больше, вы можете прочитать
этот раздел .
APP_ENV и APP_DEBUG
Консольные команды выполняются в окружении , определённом в
переменной APP_ENV
файла .env
, по умолчанию - dev
. Он также считывает
значение APP_DEBUG
, чтобы включать и выключать режим "отладки" (по умолчанию -
1
, то есть включён).
Чтобы запустить команду в другом окружении или режиме отладки, отредактируйте значение
APP_ENV
и APP_DEBUG
.
1 2
# очищает кеш для окружения производства
$ APP_ENV=prod php bin/console cache:clear
Заполнение Console
Если вы используете оболочку Bash, Zsh или Fish, вы можете установить скрипт заполнения Symfony, чтобы получить автозаполнение при вводе команд в терминал. Все команды поддерживают заполенение омени и опций, а некоторые могут даже заполнять значения.
Для начала, вам нужно единожды установить скрипт заполнения. Выполните
bin/console completion --help
для инструкций по установке для вашей
оболочки.
Note
При использовании Bash, убедитесь в том, что вы установили и настроили пакет
"bash completion" для вашей ОС (обычно называется bash-completion
).
После установки и перезагрузки вашего терминала, вы готовы использовать заполнение (по умолчанию, путём нажатия клавиши таб).
Tip
Многие инструменты PHP созданы с использованием компонента Symfony Console (например, Composer, PHPstan и Behat). Если они используют версию 5.4 или выше, вы также можете установить из скрипт заполнения, чтобы подключить заполнение консоли:
1 2
$ php vendor/bin/phpstan completion --help
$ composer completion --help
Создание команды
Команды определяются в классах, расширяющих 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
// src/Command/CreateUserCommand.php
namespace App\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
// the name of the command is what users type after "php bin/console"
#[AsCommand(name: 'app:create-user')]
class CreateUserCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output): int
{
// ... введите здесь код, чтобы создать пользователя
// этот метод должен вернуть целое число с "кодом завершения"
// команды. Вы также можете использовать это константы, чтобы сделать код более читаемым
// вернуть это, если при выполнении команды не было проблем
// (эквивалентно возвращению int(0))
return Command::SUCCESS;
// или вернуть это, если во время выполнения возникла ошибка
// (эквивалентно возвращению int(1))
// return Command::FAILURE;
// или вернуть это, чтобы указать на неправильное использование команды, например, невалидные опции
// или отсутствующие аргументы (равноценно возвращению int(2))
// return Command::INVALID
}
}
Конфигурация команды
Вы можете по желанию определить описание, сообщение помощи и
аргументы и опции ввода by overriding the
configure()
method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// src/Command/CreateUserCommand.php
// ...
class CreateUserCommand extends Command
{
// ...
protected function configure(): void
{
$this
// описание команды, которое отображается при запуске "php bin/console list"
->setDescription('Creates a new user.')
// помощь команды, которая отображается при запуске команды с опцией "--help"
->setHelp('This command allows you to create a user...')
;
}
}
Tip
Определение статического свойства $defaultDescription
вместо использования метода
setDescription()
, позволяет получать описание команды без инстанциирования ее класса.
Это делает выполнение команды php bin/console list
значительно быстрее.
Если вы хотите всегда быстро выполнять команду list
, добавьте к ней опцию --short
(php bin/console list --short
). Таким образом вы избежите инстанциированния классов
команды, но и не будете получать отображение описания команд, которые используют метод
setDescription()
вместо статического свойства.
Метод configure()
вызывается автоматически в конце конструктора команды.
Если ваша команда определяет свой конструктор, сначала установите свойства
и вызовите родительский конструктор для того, чтобы эти свойства стали
доступны в методе configure()
:
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
// ...
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
class CreateUserCommand extends Command
{
// ...
public function __construct(bool $requirePassword = false)
{
// лучшие практики рекомендуют вызывать сначала родительский конструктор и
// потом установка своих свойств. Это не сработает в данном случае
// потому что configure() нуждается в установленных свойствах в конструкторе
$this->requirePassword = $requirePassword;
parent::__construct();
}
protected function configure(): void
{
$this
// ...
->addArgument('password', $this->requirePassword ? InputArgument::REQUIRED : InputArgument::OPTIONAL, 'User password')
;
}
}
Регистрация команды
В версиях PHP 8 и новее, вы можете зарегистрировать команду, добавив к ней атрибут
AsCommand
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// src/Command/CreateUserCommand.php
namespace App\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
#[AsCommand(
name: 'app:create-user',
description: 'Creates a new user.',
hidden: false,
aliases: ['app:add-user']
)]
class CreateUserCommand extends Command
{
// ...
}
Если вы не можете использовать PHP-атрибуты, зарегистрируйте команду как сервис и
тегируйте её тегом console.command
. Если вы
используете конфигурацию services.yaml по умолчанию ,
это уже сделано за вас, благодаря автоконфигурации .
Выполнение команды
После конфигурации и регистрации команды вы можете выполнить её в терминале:
1
$ php bin/console app:create-user
Как вы могли ожидать эта команда ничего не делает, так как вы пока не прописали никакой логики.
Добавьте свою логику в метод execute()
.
Вывод консоли
Метод execute()
имеет доступ к потоку вывода для того, чтобы писать сообщения в
консоль:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// ...
protected function execute(InputInterface $input, OutputInterface $output): int
{
// выводит множество строк в консоль (добавляя "\n" в конце каждой строки)
$output->writeln([
'User Creator',
'============',
'',
]);
// значение возвращённое someMethod() может быть итератором (https://secure.php.net/iterator)
// которое генерирует и возвращает сообщение с помощью ключевого слова PHP 'yield'
$output->writeln($this->someMethod());
// выводит сообщение с последующим "\n"
$output->writeln('Ух ты!');
// выводит сообщение, не добавляя "\n" в конце строки
$output->write('You are about to ');
$output->write('create a user.');
return Command::SUCCESS;
}
Теперь, попробуйте выполнить команду:
1 2 3 4 5 6
$ php bin/console app:create-user
User Creator
============
Ух ты!
Вы уже почти создали пользователя.
Секции вывода
Обычный вывод консоли может быть разделён на несколько независимых регионов называемых "секции вывода". Создайте одну или несколько данных секций, когда вам нужно очистить и перезаписать выводимую информацию.
Секции создаются методом ConsoleOutput::section() который возвращает экземпляр ConsoleSectionOutput:
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 33 34 35 36 37 38 39 40 41 42 43 44
// ...
use Symfony\Component\Console\Output\ConsoleOutputInterface;
class MyCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (!$output instanceof ConsoleOutputInterface) {
throw new \LogicException('This command accepts only an instance of "ConsoleOutputInterface".');
}
$section1 = $output->section();
$section2 = $output->section();
$section1->writeln('Hello');
$section2->writeln('World!');
sleep(1);
// Вывод отображает "Hello\nWorld!\n"
// overwrite() заменяет все существующее содержание секции заданным содержанием
$section1->overwrite('Goodbye');
sleep(1);
// Теперь вывод отображает "Goodbye\nWorld!\n"
// clear() удаляет все содержание раздела...
$section2->clear();
sleep(1);
// Теперь вывод отображает "Goodbye\n"
// ...но вы также можете удалить заданное количество строк
// (этот пример удаляет две последние строки секции)
$section1->clear(2);
sleep(1);
// Теперь вывод абсолютно пуст!
// установка максимальной высоты раздела заставит новые строки заменить старые
$section1->setMaxHeight(2);
$section1->writeln('Line1');
$section1->writeln('Line2');
$section1->writeln('Line3');
return Command::SUCCESS;
}
}
Note
Новая строка добавляется автоматически при отображении информации в секции.
Секции вывода позволяют вам манипулировать выводом консоли сложными способами, например, отображение нескольких прогрессбаров , которые обновляются независимо друг от друга и добавление строк в таблицы , которые уже были выведены.
Caution
Терминалы позволяют перезаписывать только видимое содержание, поэтому необходимо учитывать высоту консоли при попытке записи/перезаписи содержания раздела.
Ввод консоли
Используйте опции или аргументы ввода, чтобы передать информацию в команду:
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
use Symfony\Component\Console\Input\InputArgument;
// ...
protected function configure(): void
{
$this
// configure an argument
->addArgument('username', InputArgument::REQUIRED, 'The username of the user.')
// ...
;
}
// ...
public function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln([
'User Creator',
'============',
'',
]);
// получить значение аргумента, используя getArgument()
$output->writeln('Username: '.$input->getArgument('username'));
return Command::SUCCESS;
}
Теперь вы можете передать имя пользователя в команду:
1 2 3 4 5
$ php bin/console app:create-user Wouter
User Creator
============
Username: Wouter
See also
Смотрите Ввод консоли (аргументы и опции), чтобы узнать больше информации об опциях и аргументах консоли.
Получение сервисов из сервис-контейнера
Чтобы действительно создать нового пользователя, команда должна получить доступ
к некоторым сервисам. Так как ваша команда уже зарегистрирована,
как сервис, вы можете использовать нормальное внедрение зависимости. Представьте,
что у вас есть сервис App\Service\UserManager
, к которому вы хотите получить
доступ:
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
// ...
use App\Service\UserManager;
use Symfony\Component\Console\Command\Command;
class CreateUserCommand extends Command
{
public function __construct(
private UserManager $userManager,
){
parent::__construct();
}
// ...
protected function execute(InputInterface $input, OutputInterface $output): int
{
// ...
$this->userManager->create($input->getArgument('username'));
$output->writeln('User successfully generated!');
return Command::SUCCESS;
}
}
Жизненный цикл команды
Команды имеют три метода жизненного цикла, которые активируются при выполнении команды:
- initialize() (необязательный)
-
Этот метод выполняется до методов
interact()
иexecute()
. Его главная цель - инициализировать переменные, используемые в других методах команды. - interact() (необязательный)
-
Этот метод выполняется после
initialize()
и доexecute()
. Его цель - проверка наличия всех опций/аргументов и спросить пользователя значения в диалоговом режиме. Это последнее место, где вы можете запросить отсутствующие опции/аргументы. После этой команды, отсутствующие опции/аргументы будут приводить к ошибке. - execute() (обязательный)
-
Этот метод выполняется после
interact()
иinitialize()
. Он содержит логику, которую вы хотите выполнить с помощью команды.
Тестирование команд
Symfony предоставляет несколько инструментов, чтобы помочь вам тестировать ваши команды. Самая полезная - это класс CommandTester. Он использует специальные классы ввода и вывода, чтобы облегчить тестирование без настоящей консоли:
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 33 34 35
// tests/Command/CreateUserCommandTest.php
namespace App\Tests\Command;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Console\Tester\CommandTester;
class CreateUserCommandTest extends KernelTestCase
{
public function testExecute(): void
{
self::bootKernel();
$application = new Application(self::$kernel);
$command = $application->find('app:create-user');
$commandTester = new CommandTester($command);
$commandTester->execute([
// передать аргументы помощнику
'username' => 'Wouter',
// добавить к ключу префикс с двумя дефисами при передаче опций,
// например: '--some-option' => 'option_value',
// используйте скобки для тестиования значения массива,
// например: '--some-option' => ['option_value'],
]);
$commandTester->assertCommandIsSuccessful();
// вывод команды в консоли
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Username: Wouter', $output);
// ...
}
}
Если вы используете приложение одной команды,
вызовите setAutoExit(false)
, чтобы получить результат команды в CommandTester
.
Tip
Вы также можете тестировать всю консоль приложения, используя ApplicationTester.
Caution
При тестировании команд с использованием класса CommandTester
, события консоли
не запускаются. Если вам нужно протестировать эти события, используйте вместо этого
ApplicationTester.
Caution
При тестировании команд с использованием класса ApplicationTester, не забудьте отключить автоматический выход:
1 2 3 4
$application = new Application();
$application->setAutoExit(false);
$tester = new ApplicationTester($application);
Caution
При тестировании опций команды InputOption::VALUE_NONE
, вы должны передать
им пустое значение:
1 2
$commandTester = new CommandTester($command);
$commandTester->execute(['--some-option' => '']);
Note
При использовании компонента Console в отдельном проекте, используйте
Symfony\\Component\\Console\\Application
и расширьте обычный \PHPUnit\Framework\TestCase
.
При тестировании команд может быть полезно понять, как ваша команда реагирует на различные настройки, такие как ширина и высота терминала или даже используемый цветовой режим. Вы можете получить доступ к такой информации благодаря классу Terminal:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
use Symfony\Component\Console\Terminal;
$terminal = new Terminal();
// получает количество доступных строчек
$height = $terminal->getHeight();
// получает количество доступных колонок
$width = $terminal->getWidth();
// получает цветовой режим
$colorMode = $terminal->getColorMode();
// изменяет цветовой режим
$colorMode = $terminal->setColorMode(AnsiColorMode::Ansi24);
Ведение логов ошибок команды
Какждый раз, когда во время выполнения команды вызывается исключение, Symfony
добавляет для него сообщение лога, включая всю неработающую команду. Кроме того,
Symfony регистрирует подписчика событий, чтобы слушать
ConsoleEvents::TERMINATE event и добавляет сообщение
лога каждый раз, когда команда не заканчивается 0
exit status.
Использование событий и обработка сигналов
Во время выполнения команды происходит множество событий, одно из которых позволяет реагировать на сигналы, подробнее читайте в этом разделе.
Профилирование команд
Symfony позволяет профилировать выполнение любой команды, в том числе и вашей. Во-первых,
убедитесь, что включены режим отладки и профилировщик.
Затем добавьте опцию --profile
при выполнении команды:
1
$ php bin/console --profile app:my-command
Теперь Symfony будет собирать данные о выполнении команды, что будет полезно для
отладки ошибок или проверки других проблем. Когда выполнение команды закончится,
профиль будет доступен через веб-страницу профилировщика.
Tip
Если вы запустите команду в режиме подробного описания (добавив опцию -v
), Symfony
отобразит в выводе кликабельную ссылку на профиль команды (если ваш терминал поддерживает
ссылки). Если вы запустите команду в режиме отладки (-vvv
), вы также увидите время и
память, потребляемые командой.
Caution
При профилировании команды messenger:consume
из компонента Messenger
добавьте в команду опцию no-reset
, иначе вы не получите никакого профиля. Кроме того,
рассмотрите возможность использования опции --limit
, чтобы обрабатывать только несколько
сообщений, для того, чтобы сделать профиль более читаемым в профилировщике.
Узнайте больше
- Как вызывать другие команды
- Как раскрашивать и стилизовать вывод консоли
- Как вызвать команду из контроллера
- Как определять команды, как сервисы
- Как скрывать консольные команды
- Ввод консоли (аргументы и опции)
- Как сделать команды ленивой загрузки
- Предотвращение многократного выполения консольной команды
- Как генерировать URL из консоли
- Как оформить консольную команду
- Уровни детализации
Компонент Console также содержит набор "помощников" - разных маленьких инструментов, способных помочь вам с разными заданиями:
- Помощник Question: узнает у пользователя информацию в диалоговом режиме
- Помощник Formatter: настраивает расцвеичвание вывода
- Индикатор выполнения: показывает бар прогресса
- Індикатор прогресса: показывает индикатор прогресса
- Таблица: отображает данные в табличной форме
- Помощник Debug Formatter: предоставляет функции для вывода
информации отладки при запуске внешней программы
Помощник Process: позволяет вам запустить процесс с использованием DebugFormatterHelper
Помощник Cursor: позволяет манипулировать курсором в терминале