Створення консольних команд
Команда — клас, що успадковує
Symfony\Component\Console\Command\Command.
Залежності передаються через конструктор (автовайринг контейнера);
логіка — у методі execute().
Див. також:
Робота з консоллю
(провайдери та залежності,
DisabledCommand),
автовайринг.
Документація Symfony: Creating a Command, Input, Output styling.
Мінімальна команда
<?php declare(strict_types=1);
namespace Concept\App\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
final class GreetCommand extends Command
{
protected function configure(): void
{
$this->setName('app:greet')
->setDescription('Print a greeting');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->success('Hello from Concept Core');
return Command::SUCCESS;
}
}
Реєстрація в застосунку
Додайте клас у config/commands.php:
return [
'commands' => [
// ...команди ядра
GreetCommand::class,
],
];
ConsoleServiceProvider робить $container->get(GreetCommand::class)
і addCommand(). Якщо в конструкторі потрібні сервіси — вони резолвляться автоматично
через ReflectionContainer.
Якщо залежність не зареєстрована (немає потрібного провайдера в
bootstrap/providers/console.php), замість вашої команди з’явиться
DisabledCommand — див. консоль → disabled.
php bin/console.php app:greet
Провайдери для вашої команди
Типові залежності власних команд і що підключити в CLI:
| Залежність у конструкторі | Провайдер у console.php |
|---|---|
UserModel, DatabaseInterface | DatabaseServiceProvider |
ConfigInterface | ConfigServiceProvider |
RouterInterface | HttpServiceProvider |
LoggerInterface | LogServiceProvider |
| сервіс компонента | провайдер компонента + ComponentsServiceProvider |
Команда без конструктора (як GreetCommand) залежить лише від
ConsoleServiceProvider. Після зміни console.php перезапустіть
php bin/console.php list і переконайтеся, що немає червоного «disabled».
Аргументи та опції
Приклад — UserListCommand (user:list):
use Concept\Components\AuthAdmin\Models\UserModel;
use Symfony\Component\Console\Input\InputOption;
class UserListCommand extends Command
{
private const string COMMAND_NAME = 'user:list';
protected function configure(): void
{
$this->setName(self::COMMAND_NAME)
->setDescription('Display a list of registered users')
->addOption('limit', 'l', InputOption::VALUE_OPTIONAL, 'How many users?', 10);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$limit = is_numeric($input->getOption('limit'))
? (int) $input->getOption('limit')
: 10;
$users = UserModel::query()->limit($limit)->get()->toArray();
$io->table(array_keys($users[0] ?? []), $users);
return Command::SUCCESS;
}
}
Для узгодженості з моделями через DI краще інжектувати
UserModel і викликати $this->userModel->newQuery():
public function __construct(
private readonly UserModel $userModel,
) {
parent::__construct();
}
Потрібен DatabaseServiceProvider у CLI — інакше команда стане disabled.
Приклад з ядра: DI в команді
RouteListCommand отримує RouterInterface — потрібен HttpServiceProvider:
use Concept\Core\Http\Routing\Contracts\RouterInterface;
public function __construct(private readonly RouterInterface $router)
{
parent::__construct();
}
DbMigrateCommand — Migrator + MigrationRegistry.
Складні команди ядра лежать у Concept\Core\Console\Commands.
Команда в компоненті
- Створіть
Components/MyModule/Commands/MyCommand.php - Додайте клас у
commands()компонента - Переконайтеся, що компонент увімкнено в
config/components.php
// AuthAdminComponent::commands()
public function commands(): array
{
return [UserListCommand::class];
}
Під час ComponentsServiceProvider::boot() команди резолвяться з контейнера і
додаються в ConsoleApplication через addCommand().
ConsoleServiceProvider має бути зареєстрований раніше у
bootstrap/providers/console.php.
Якщо команда компонента потребує БД або HTTP-сервісів — у CLI все одно потрібні відповідні провайдери ядра (див. таблицю вище).
Вивід і помилки
$io = new SymfonyStyle($input, $output);
$io->title('Import started');
$io->writeln('Processing...');
$io->success('Done');
$io->warning('Partial import');
$io->error('Failed');
// таблиця
$io->table(['Column A', 'Column B'], $rows);
// progress (довгі цикли)
$io->progressStart(count($items));
foreach ($items as $item) {
// ...
$io->progressAdvance();
}
$io->progressFinish();
При винятку повертайте Command::FAILURE або дозвольте Symfony вивести stack trace
(у dev з Whoops для CLI — plain text).
Чеклист
- Унікальне ім’я команди (
module:action, наприкладbilling:sync) configure()— name, description, arguments/options; константаCOMMAND_NAMEяк у ядріexecute()— коротка orchestration, важке в сервісі;Command::SUCCESS/FAILURE- Реєстрація в
config/commands.phpабо вcommands()компонента - Провайдери CLI покривають усі залежності конструктора
- Перевірка:
php bin/console.php list(без «disabled») іhelp your:command
Не дублюйте HTTP-контролери в CLI: винесіть спільну логіку в Services/
і викличте її і з web, і з command.
Команда «disabled» — це майже завжди відсутній провайдер у console.php, а не помилка в execute().