Урок 15: Командная строка (Console) в Symfony

В 15-ом уроке мы изучимв один из инструментов Symfony, это консоль. Умение работать с CLI (Command Line Interface) не только ускорит вашу разработку, но и откроет новые возможности для автоматизации задач. Мы разберём создание команд, работу с аргументами, интеграцию с Doctrine и даже настроим рассылку писем через консоль.

Зачем Symfony CLI?

С её помощью вы можете:

  1. Генерировать код (контроллеры, сущности, миграции).
  2. Запускать фоновые задачи (например, обработку очередей).
  3. Управлять Doctrine (миграции, фикстуры).
  4. Создавать кастомные скрипты для автоматизации.

Все вы уже использовали команду php bin/console make:controller. Теперь научимся создавать такие команды сами.

Создание консольных команд

Каждая команда в Symfony это класс, унаследованный от Command. Давайте создадим простую команду для приветствия пользователя.

Шаг 1: Генерация класса команды

Запустите в консоли:

bash
php bin/console make:command greeting

Система создаст класс GreetingCommand в src/Command/.

Шаг 2: Настройка команды

Откройте src/Command/GreetingCommand.php:

php
<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class GreetingCommand extends Command
{
    protected static $defaultName = 'app:greet';

    protected function configure(): void
    {
        $this->setDescription('Выводит приветственное сообщение');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $output->writeln('Привет, Symfony-разработчик!');
        return Command::SUCCESS;
    }
}

Шаг 3: Запуск команды

Выполните:

bash
php bin/console app:greet

Увидите вывод: Привет, Symfony-разработчик!

Аргументы и опции команд

Аргументы (arguments) обязательные параметры. Опции (options) необязательные, с флагами (например, --send-email).

Пример: Команда с аргументом и опцией

Модифицируем GreetingCommand:

php
protected function configure(): void
{
    $this
        ->setDescription('Приветствие пользователя')
        ->addArgument('name', InputArgument::REQUIRED, 'Имя пользователя')
        ->addOption('yell', 'y', InputOption::VALUE_NONE, 'Вывести сообщение заглавными буквами');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
    $name = $input->getArgument('name');
    $text = "Привет, $name!";

    if ($input->getOption('yell')) {
        $text = strtoupper($text);
    }

    $output->writeln($text);
    return Command::SUCCESS;
}

Использование:

bash
php bin/console app:greet Максим       # Вывод: Привет, Максим!
php bin/console app:greet Максим --yell # Вывод: ПРИВЕТ, МАКСИМ!

Взаимодействие с Doctrine из CLI

Symfony предоставляет встроенные команды для работы с Doctrine. Например:

  • doctrine:database:create — создать БД.
  • doctrine:migrations:diff — сгенерировать миграцию.
  • doctrine:fixtures:load — загрузить фикстуры.

Создадим кастомную команду для подсчёта пользователей

Цель: Вывести количество пользователей в базе данных.

php
// src/Command/UserCountCommand.php

namespace App\Command;

use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class UserCountCommand extends Command
{
    protected static $defaultName = 'app:user:count';

    public function __construct(private EntityManagerInterface $em)
    {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->setDescription('Подсчёт пользователей в базе');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $count = $this->em->getRepository(User::class)->count([]);
        $output->writeln("Пользователей в базе: $count");
        return Command::SUCCESS;
    }
}

Запуск:

bash
php bin/console app:user:count

Автоматизация задач: рассылка писем

Допустим, нам нужно отправлять еженедельный дайджест пользователям. Создадим команду для этого.

Шаг 1: Подготовка сервиса рассылки

Предположим, у вас есть сервис EmailService с методом sendWeeklyDigest(). Инжектируем его в команду.

php
// src/Command/SendDigestCommand.php

namespace App\Command;

use App\Service\EmailService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class SendDigestCommand extends Command
{
    protected static $defaultName = 'app:send:digest';

    public function __construct(private EmailService $emailService)
    {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this->setDescription('Рассылка еженедельного дайджеста');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $users = // ... логика получения пользователей;
        
        foreach ($users as $user) {
            $this->emailService->sendWeeklyDigest($user);
            $output->writeln("Отправлено письмо: {$user->getEmail()}");
        }

        $output->writeln('Рассылка завершена!');
        return Command::SUCCESS;
    }
}

Шаг 2: Запуск через Cron

Для автоматизации добавьте задание в cron:

bash
0 8 * * 1 /usr/bin/php /var/www/project/bin/console app:send:digest >> /var/log/digest.log

Это будет запускать команду каждый понедельник в 8 утра.

Практические задания

  1. Задание 1: Создайте команду app:user:create, которая принимает имя пользователя (аргумент) и опцию --admin (если есть, устанавливает роль ADMIN).
  2. Задание 2: Напишите команду для очистки старых логов (например, старше 30 дней). Используйте Doctrine для работы с базой.
  3. Задание 3: Реализуйте команду, которая генерирует CSV-отчёт о заказах за указанный период (используйте аргументы для дат начала и конца).

Пример решения для задания 1

php
// src/Command/CreateUserCommand.php

// ... namespace и импорты

class CreateUserCommand extends Command
{
    protected static $defaultName = 'app:user:create';

    public function __construct(private UserPasswordHasherInterface $hasher, private EntityManagerInterface $em)
    {
        parent::__construct();
    }

    protected function configure(): void
    {
        $this
            ->addArgument('username', InputArgument::REQUIRED, 'Логин пользователя')
            ->addOption('admin', null, InputOption::VALUE_NONE, 'Сделать администратором');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $user = new User();
        $user->setUsername($input->getArgument('username'));
        $user->setPassword($this->hasher->hashPassword($user, 'temp_password'));
        
        if ($input->getOption('admin')) {
            $user->setRoles(['ROLE_ADMIN']);
        }

        $this->em->persist($user);
        $this->em->flush();

        $output->writeln('Пользователь создан! ID: ' . $user->getId());
        return Command::SUCCESS;
    }
}

Сегодня вы научились создавать консольные команды, работать с аргументами и опциями, взаимодействовать с Doctrine и автоматизировать задачи. Эти навыки важны для профессиональной работы с Symfony.

Впереди ещё много интересного. Полный курс с уроками по Symfony для начинающих ждёт вас здесь: https://max-gabov.ru/symphony-dlya-nachinaushih

Поделиться статьей:
Поддержать автора блога

Поддержка автора осуществляется с помощью специальной формы ниже, предоставленной сервисом «ЮMoney». Все платёжные операции выполняются на защищённой странице сервиса, что обеспечивает их корректность и полную безопасность.

Персональные рекомендации
Оставить комментарий