Навигация
Присоединяйтесь к нашему Telegram-каналу!☝

Будьте в курсе последних новинок и фишек e-commerce: советы, полезные инструменты и эксклюзивные материалы.

Блог Rss rss_feed

CQRS в PrestaShop 9: Commands, Queries и современная архитектура модулей

CQRS в PrestaShop 9: Commands, Queries и современная архитектура модулей

Современный PrestaShop постепенно уходит от подхода, когда вся логика находится прямо внутри контроллера.

Раньше изменение товара часто выглядело примерно так:

$product = new Product($idProduct);
$product->active = false;
$product->save();

Такой код понятен и продолжает работать, но в современных Symfony-разделах Back Office всё чаще используется другой подход — CQRS.

CQRS расшифровывается как Command Query Responsibility Segregation. Главная идея проста:

  • Command изменяет данные;

  • Query получает данные.

Что такое Command

Command описывает конкретное действие.

Например:

UpdateProductPriceCommand
ChangeOrderStatusCommand
DisableProductCommand

Сам Command ничего не сохраняет в базе данных. Он только содержит необходимые для операции данные.

final class DisableProductCommand
{
    public function __construct(
        private int $productId
    ) {
    }

    public function getProductId(): int
    {
        return $this->productId;
    }
}

Команда передаётся обработчику через Command Bus.

$this->getCommandBus()->handle(
    new DisableProductCommand($idProduct)
);

Что делает Command Handler

Вся реальная логика находится в Handler.

final class DisableProductHandler
{
    public function handle(
        DisableProductCommand $command
    ): void {
        $product = new Product(
            $command->getProductId()
        );

        if (!Validate::isLoadedObject($product)) {
            throw new PrestaShopException(
                'Product not found'
            );
        }

        $product->active = false;
        $product->save();
    }
}

Получается следующая схема:

Controller
    ↓
Command
    ↓
Command Bus
    ↓
Handler
    ↓
Product / Repository / Database

Контроллер больше не обязан знать, каким способом изменяется товар.

Что такое Query

Query работает похожим образом, но используется для получения информации.

Например:

GetProductForEditing
GetOrderForViewing
GetCategoryData

Контроллер отправляет Query:

$productData = $this->getQueryBus()->handle(
    new GetProductForEditing($idProduct)
);

Query Handler получает необходимые данные и возвращает результат.

Схема выглядит так:

Controller
    ↓
Query
    ↓
Query Bus
    ↓
Query Handler
    ↓
Data

Таким образом операции чтения и изменения данных не смешиваются.

Зачем PrestaShop использует CQRS

Одна из причин — постепенный переход Back Office на Symfony.

В старой архитектуре контроллер напрямую работал с ObjectModel:

Controller → Product → Database

В современной архитектуре появляется дополнительный слой:

Controller
    ↓
Command / Query
    ↓
Handler
    ↓
ObjectModel / Repository

Благодаря этому Symfony-контроллер меньше зависит от того, каким способом PrestaShop хранит или изменяет данные.

Это особенно удобно в большой платформе, где одновременно существуют legacy-код, ObjectModel, Symfony и новые Domain-компоненты.

CQRS не запрещает ObjectModel

Иногда возникает впечатление, что при использовании CQRS больше нельзя обращаться к:

new Product();
new Order();
new Category();

Это не так.

Handler вполне может использовать привычный ObjectModel.

Разница только в том, что работа с ним находится не внутри контроллера, а в отдельном слое.

Например:

Controller
    ↓
UpdateProductCommand
    ↓
UpdateProductHandler
    ↓
Product ObjectModel

Если в дальнейшем реализация изменится, контроллер переписывать не придётся.

Где CQRS особенно полезен в модулях

Не стоит использовать такую архитектуру в каждом небольшом модуле.

Если модуль просто выводит дополнительный блок через hook, CQRS может только усложнить проект.

Но подход становится полезным, если модуль содержит:

  • сложный Back Office;

  • несколько Symfony-контроллеров;

  • импорт товаров;

  • синхронизацию с API;

  • управление заказами;

  • CLI-команды;

  • cron;

  • AJAX;

  • большое количество бизнес-операций.

Например, одна операция синхронизации остатков может запускаться из нескольких мест:

Back Office
CLI
Cron
API

Вместо четырёх разных реализаций все они могут вызывать одну команду:

UpdateProductStockCommand
        ↓
UpdateProductStockHandler

Бизнес-логика остаётся в одном месте.

Как организовать структуру модуля

Для крупного модуля можно использовать примерно такую структуру:

src/
├── Controller/
├── Command/
├── CommandHandler/
├── Query/
├── QueryHandler/
├── DTO/
└── Exception/

Например:

Command/
    UpdateProductPriceCommand.php

CommandHandler/
    UpdateProductPriceHandler.php

Query/
    GetProductData.php

QueryHandler/
    GetProductDataHandler.php

Такой код легче читать и сопровождать.

Главная ошибка при использовании CQRS

Не нужно просто переносить огромный контроллер в огромный Handler.

Плохой вариант:

public function handle($command)
{
    // 500 строк логики
}

Если операция сложная, Handler должен обращаться к отдельным сервисам:

UpdateProductHandler
    ↓
ProductValidator
PriceCalculator
StockService
ExternalApiService

CQRS помогает разделить ответственность, а не просто увеличить количество файлов.

Стоит ли использовать CQRS в собственном модуле

Для маленького модуля — необязательно.

Для большого модуля, который планируется поддерживать несколько лет, такой подход часто оправдан.

Особенно если одна бизнес-операция должна выполняться из разных мест.

Простой ориентир:

Простой hook → CQRS, скорее всего, не нужен.

Большой Symfony Back Office → стоит рассмотреть.

CLI + cron + API + Back Office → CQRS особенно полезен.

CQRS в PrestaShop можно свести к простой схеме.

Изменение данных:

Controller
    ↓
Command
    ↓
Handler

Получение данных:

Controller
    ↓
Query
    ↓
Handler

Для разработчика это даёт главное преимущество: бизнес-логика перестаёт зависеть от конкретного контроллера.

Это особенно важно для современных модулей PrestaShop с Back Office, импортом, API, CLI и сложной логикой.

Кроме того, понимание Commands, Queries и Handlers заметно упрощает чтение исходного кода самого PrestaShop 9.

Был ли этот пост полезен для вас?

    
👈 Присоединяйтесь к нашему Telegram-каналу!

Будьте в курсе последних новинок и фишек e-commerce: советы, полезные инструменты и эксклюзивные материалы.

👈 Присоединяйтесь к нашему Telegram-каналу!

Будьте в курсе последних новинок и фишек e-commerce: советы, полезные инструменты и эксклюзивные материалы.

На данный момент комментариев нет
close

Checkout

close

Избранное

Promo