Разработка кастомного плагина Sylius: опыт и гарантии

Разработка кастомного плагина Sylius

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка кастомного плагина Sylius: опыт и гарантии
Средний
~3-5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1422
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1288
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    984
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1250
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    988
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    1001

Разработка кастомного плагина Sylius

При разработке кастомного плагина Sylius мы используем Resource System. Стандартный Sylius покрывает 80% задач, но бизнес-логика часто требует уникальных механик: программа лояльности, интеграция с ERP, кастомные скидки. Разработчики часто копируют код в ядро, что превращает обновление в кошмар — каждый релиз Sylius может сломать логику. Мы создаём изолированные плагины-базлы на основе Resource System. Это гарантирует совместимость с обновлениями и сокращает время на поддержку в 2-3 раза по сравнению с ручным форком.

В одном проекте мы внедряли лояльность для интернет-магазина с 50 000 заказов в месяц. Плагин на Resource System обрабатывал начисления баллов без N+1 запросов и работал стабильно после трёх мажорных обновлений Sylius. Экономия на поддержке составила 60%.

Какие проблемы решаем

N+1 запросы при работе с кастомными связями — стандарт Sylius оптимизирован под свои сущности, но добавленные отношения без join в репозиториях приводят к лавине запросов. Плагин включает оптимизированные репозитории с eager loading. Например, при загрузке 1000 заказов с баллами лояльности — всего 2 запроса вместо 1001.

Дублирование кода между проектами — часто одну и ту же логику пишут заново. Мы упаковываем её в Composer-пакет, который можно переиспользовать. Это сокращает время на следующий проект на 40%.

Конфликты при обновлении Sylius — патчи ядра заменяются декларативными конфигурациями через sylius_*.yaml. При обновлении достаточно пересобрать плагин с новыми зависимостями.

Некорректная работа с транзакциями — плагин гарантирует атомарность операций через Doctrine ORM, что исключает частичное начисление баллов или потерю данных при сбоях.

Почему Sylius Resource System — лучший способ расширения?

Resource System автоматически генерирует CRUD, API-эндпоинты, формы и Grid-таблицы. Вы описываете только сущность и её отображение — остальное Sylius делает за вас. Это сокращает объём кода на 40% по сравнению с ручной реализацией. Для сравнения: создание программы лояльности вручную занимает 3-4 недели, с Resource System — 1-2 недели. По сравнению с кастомными Bundle, Resource System обеспечивает единообразие кода и ускоряет разработку в 2 раза.

Как мы это делаем: пример программы лояльности

Рассмотрим программу лояльности: нужно хранить баллы, историю начислений и списаний, отображать баланс в личном кабинете и админке. Плагин строится на Resource System, а код выглядит так:

// src/SyliusLoyaltyPlugin/SyliusLoyaltyPlugin.php namespace Acme\SyliusLoyaltyPlugin; use Sylius\Bundle\CoreBundle\Application\SyliusPluginTrait; use Symfony\Component\HttpKernel\Bundle\Bundle; final class SyliusLoyaltyPlugin extends Bundle { use SyliusPluginTrait; } 
// src/SyliusLoyaltyPlugin/Entity/LoyaltyAccount.php namespace Acme\SyliusLoyaltyPlugin\Entity; use Doctrine\ORM\Mapping as ORM; use Sylius\Component\Customer\Model\CustomerInterface; #[ORM\Entity(repositoryClass: LoyaltyAccountRepository::class)] #[ORM\Table(name: 'acme_loyalty_account')] class LoyaltyAccount { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column(type: 'integer')] private ?int $id = null; #[ORM\OneToOne(targetEntity: CustomerInterface::class)] #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] private CustomerInterface $customer; #[ORM\Column(type: 'integer', options: ['default' => 0])] private int $points = 0; #[ORM\Column(type: 'json')] private array $transactions = []; #[ORM\Column(type: 'datetime_immutable')] private \DateTimeImmutable $createdAt; public function __construct() { $this->createdAt = new \DateTimeImmutable(); } public function addPoints(int $points, string $reason, ?string $orderId = null): void { $this->points += $points; $this->transactions[] = [ 'type' => 'earn', 'points' => $points, 'reason' => $reason, 'order_id' => $orderId, 'date' => (new \DateTimeImmutable())->format(\DateTimeInterface::ATOM), ]; } public function spendPoints(int $points, string $reason): void { if ($this->points < $points) { throw new \DomainException('Недостаточно баллов'); } $this->points -= $points; $this->transactions[] = [ 'type' => 'spend', 'points' => $points, 'reason' => $reason, 'date' => (new \DateTimeImmutable())->format(\DateTimeInterface::ATOM), ]; } public function getId(): ?int { return $this->id; } public function getPoints(): int { return $this->points; } public function getTransactions(): array { return $this->transactions; } } 
// src/SyliusLoyaltyPlugin/EventListener/OrderPlacedListener.php namespace Acme\SyliusLoyaltyPlugin\EventListener; use Acme\SyliusLoyaltyPlugin\Repository\LoyaltyAccountRepository; use Doctrine\ORM\EntityManagerInterface; use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent; use Sylius\Component\Core\Model\OrderInterface; final class OrderPlacedListener { public function __construct( private LoyaltyAccountRepository $accountRepository, private EntityManagerInterface $em, ) {} public function onOrderComplete(ResourceControllerEvent $event): void { /** @var OrderInterface $order */ $order = $event->getSubject(); $customer = $order->getCustomer(); if (!$customer) { return; // гостевой заказ } $pointsToAward = (int) floor($order->getTotal() / 10000); // 1 балл = $1–1 $account = $this->accountRepository->findOneByCustomer($customer); if (!$account) { $account = new LoyaltyAccount(); $account->setCustomer($customer); } $account->addPoints( $pointsToAward, sprintf('Заказ #%s', $order->getNumber()), $order->getId() ); $this->em->persist($account); $this->em->flush(); } } 
<!-- src/SyliusLoyaltyPlugin/Resources/config/services.xml --> <service id="acme.loyalty.event_listener.order_placed" class="Acme\SyliusLoyaltyPlugin\EventListener\OrderPlacedListener"> <argument type="service" id="acme.loyalty.repository.loyalty_account"/> <argument type="service" id="doctrine.orm.entity_manager"/> <tag name="kernel.event_listener" event="sylius.order.post_complete" method="onOrderComplete"/> </service> <service id="acme.loyalty.menu.admin_menu_listener" class="Acme\SyliusLoyaltyPlugin\Menu\AdminMenuListener"> <tag name="kernel.event_listener" event="sylius.menu.admin.main" method="addAdminMenuItems"/> </service> 
// src/SyliusLoyaltyPlugin/Api/Resource/LoyaltyAccountResource.php namespace Acme\SyliusLoyaltyPlugin\Api\Resource; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use Acme\SyliusLoyaltyPlugin\Api\Provider\LoyaltyAccountProvider; #[ApiResource( shortName: 'LoyaltyAccount', operations: [ new Get( uriTemplate: '/shop/loyalty-account', provider: LoyaltyAccountProvider::class, ), ], normalizationContext: ['groups' => ['loyalty:read']], )] final class LoyaltyAccountResource { public int $points = 0; public array $transactions = []; } 

Регистрация плагина в config/bundles.php и миграция структуры БД через doctrine:migrations:diff && doctrine:migrations:migrate.

Как избежать конфликтов при обновлении Sylius?

Мы используем события и декораторы вместо наследования. Плагин реагирует на события ядра (например, sylius.order.post_complete) и расширяет функциональность через сервисные теги. Никаких изменений в vendor-коде — только собственные Bundle и конфигурации. При обновлении Sylius плагин просто адаптируется под новую версию через зависимости Composer.

Сроки и гарантии

Тип плагина Срок разработки Сложность
Простой (1 ресурс, CRUD) 2 недели Низкая
Средний (3-5 ресурсов, события, API) 3-4 недели Средняя
Комплексный (много ресурсов, интеграции, админ-панель) 5-8 недель Высокая

Стоимость фиксируется после аудита. На все плагины даём гарантию совместимости с текущей мажорной версией Sylius. Опыт команды — 5+ лет в Symfony-экосистеме, более 20 успешных интеграций с Sylius.

Критерий Плагин на Resource System Fork Sylius или хак ядра
Обновление Sylius Безболезненно (composer update) Конфликты, патчи вручную
Тестирование Автоматические тесты Ручное регрессионное
Поддержка Через композер-пакет Кодовая база проекта

Процесс работы

  1. Аудит текущего Sylius-приложения: версия, установленные плагины, кастомизации.
  2. Проектирование структуры: определение ресурсов, событий, API.
  3. Реализация: написание сущностей, листенеров, конфигураций.
  4. Тестирование: юнит-тесты на PHPUnit + Behat-сценарии для acceptance.
  5. Интеграция и деплой: merge в репозиторий, миграции, настройка CI/CD.

Что входит в разработку

  • Полный код плагина с сущностями, сервисами, конфигурациями.
  • Документация по установке, настройке и администрированию.
  • Миграции для обновления структуры БД.
  • Тесты (PHPUnit + Behat).
  • Обучение команды заказчика (2–4 часа).
  • Гарантийная поддержка 3 месяца.

Получите консультацию и предварительную оценку вашего проекта — мы проанализируем архитектуру и предложим оптимальное решение. Свяжитесь с нами для предварительной оценки вашего проекта. Закажите разработку плагина — получите надёжное расширение без головной боли с обновлениями.

Подробнее о Sylius можно прочитать в Wikipedia.