Писал ли консольные скрипты для Symfony?

Ответ

Да, регулярно создаю консольные команды в Symfony для различных задач: обработка данных, миграции, cron-задачи и утилиты администрирования.

Структура команды:

// src/Command/ProcessOrdersCommand.php
namespace AppCommand;

use SymfonyComponentConsoleCommandCommand;
use SymfonyComponentConsoleInputInputInterface;
use SymfonyComponentConsoleOutputOutputInterface;
use SymfonyComponentConsoleInputInputArgument;
use AppServiceOrderProcessor;

class ProcessOrdersCommand extends Command
{
    protected static $defaultName = 'app:orders:process';
    protected static $defaultDescription = 'Process pending orders';

    private OrderProcessor $orderProcessor;

    public function __construct(OrderProcessor $orderProcessor)
    {
        $this->orderProcessor = $orderProcessor;
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->addArgument('date', InputArgument::OPTIONAL, 'Process date (Y-m-d)', date('Y-m-d'));
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $date = $input->getArgument('date');
        $output->writeln(sprintf('<info>Processing orders for %s</info>', $date));

        $processed = $this->orderProcessor->processByDate($date);

        $output->writeln(sprintf('<comment>Processed %d orders</comment>', $processed));
        return Command::SUCCESS;
    }
}

Ключевые особенности:

  • Внедрение зависимостей — команды полноценные сервисы с DI
  • Стили вывода<info>, <error>, <comment> для форматирования
  • Прогресс-барProgressBar для длительных операций
  • ВопросыQuestionHelper для интерактивного ввода
  • ТестированиеCommandTester для юнит-тестов
  • Логирование — интеграция с Monolog через LoggerAwareInterface

Ответ 18+ 🔞

Бля, ну вот смотри, регулярно приходится эти консольные команды в Symfony пилить. То данные обработать, то миграции какие, то по крону задачи запустить, то админские утилиты. В общем, работа такая, ёпта.

Структура, бля, команды:

// src/Command/ProcessOrdersCommand.php
namespace AppCommand;

use SymfonyComponentConsoleCommandCommand;
use SymfonyComponentConsoleInputInputInterface;
use SymfonyComponentConsoleOutputOutputInterface;
use SymfonyComponentConsoleInputInputArgument;
use AppServiceOrderProcessor;

class ProcessOrdersCommand extends Command
{
    protected static $defaultName = 'app:orders:process';
    protected static $defaultDescription = 'Process pending orders';

    private OrderProcessor $orderProcessor;

    public function __construct(OrderProcessor $orderProcessor)
    {
        $this->orderProcessor = $orderProcessor;
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->addArgument('date', InputArgument::OPTIONAL, 'Process date (Y-m-d)', date('Y-m-d'));
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $date = $input->getArgument('date');
        $output->writeln(sprintf('<info>Processing orders for %s</info>', $date));

        $processed = $this->orderProcessor->processByDate($date);

        $output->writeln(sprintf('<comment>Processed %d orders</comment>', $processed));
        return Command::SUCCESS;
    }
}

А теперь, сука, самое интересное — ключевые фишки, которые надо знать, чтобы не быть распиздяем:

  • Внедрение зависимостей — это не просто какой-то там класс, это полноценный сервис, ёб твою мать. Все зависимости автоматом подтягиваются, красота.
  • Стили вывода — вот это вообще песня. <info>, <error>, <comment> — сразу видно, где успех, а где всё накрылось медным тазом. Без этого в консоли — манда с ушами.
  • Прогресс-бар — если операция долгая, как будто на дворе 2002-й год и ты ждёшь загрузки, то юзай ProgressBar. А то пользователь подумает, что всё в пизду полетело.
  • ВопросыQuestionHelper для интерактива. Типа «Ты уверен, чувак?». Доверия ебать ноль к юзеру, лучше переспросить.
  • ТестированиеCommandTester в помощь. Чтобы потом не орать «какого хуя не работает?!», когда на проде всё ебанько.
  • Логирование — через LoggerAwareInterface с Monolog'ом. Чтобы потом, если что, не бздеть, а знать, где и что взъебнулось.

Вот так вот, коротко и по делу. Главное — не выёбывайся со сложной логикой прямо в команде, выноси в сервисы. А то получится пиздопроебибна, а не команда.