Кастомные модули Magento 2: плагины, события, интеграция с ERP

Разработка кастомного модуля Magento 2

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

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

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

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Кастомные модули Magento 2: плагины, события, интеграция с ERP
Сложный
~1-2 недели

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

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

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

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

Разработка кастомного модуля Magento 2

Прямое изменение кода ядра Magento 2 при доработках — гарантированный путь к ошибкам при обновлениях. Типичная ситуация: магазин работает на Magento 2.4.5, вы правите файл app/code/Magento/Sales/Model/Order.php, а через полгода выходит патч безопасности 2.4.6, и ваши правки ломают обновление. Кастомный модуль изолирует бизнес-логику и взаимодействует с платформой через официальные точки расширения: Events, Observers, Plugins (Interceptors), DI и предпочтения. Это позволяет бесшовно обновлять Magento, не теряя функциональность. Хотите избежать таких проблем? Свяжитесь с нами для консультации — мы поможем спроектировать правильную архитектуру.

Мы разрабатываем кастомные модули Magento 2 более 5 лет. За это время мы столкнулись с множеством типовых проблем — от N+1 запросов в Observer до неверной последовательности модулей — и выработали оптимальные архитектурные решения. Ниже на примере создания модуля, который записывает кастомные данные при оформлении заказа и синхронизирует их с внешней системой, разберём лучшие практики.

Как создать модуль Magento 2 с нуля?

Разберём структуру типичного модуля по шагам. Шаг 1: Генерация скелета

Используйте bin/magento generate:module или создайте вручную директорию app/code/Vendor/Module. Обязательные файлы:

  • registration.php
  • etc/module.xml
  • composer.json

Пример module.xml:

<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Vendor_Module" setup_version="1.0.0"> <sequence> <module name="Magento_Sales"/> <module name="Magento_Catalog"/> </sequence> </module> </config> 

Шаг 2: Schema Patches — создание таблиц

Вместо устаревших Install/Upgrade скриптов Magento рекомендует использовать Schema Patches. Это атомарные изменения, которые применяются однократно. Пример создания таблицы с внешним ключом на catalog_product_entity:

<?php // Setup/Patch/Schema/CreateCustomEntityTable.php namespace Vendor\Module\Setup\Patch\Schema; use Magento\Framework\DB\Ddl\Table; use Magento\Framework\Setup\Patch\SchemaPatchInterface; use Magento\Framework\Setup\SchemaSetupInterface; class CreateCustomEntityTable implements SchemaPatchInterface { public function __construct( private readonly SchemaSetupInterface $schemaSetup ) {} public function apply(): void { $setup = $this->schemaSetup; $setup->startSetup(); $connection = $setup->getConnection(); $tableName = $setup->getTable('vendor_custom_entity'); if (!$connection->isTableExists($tableName)) { $table = $connection->newTable($tableName) ->addColumn('entity_id', Table::TYPE_INTEGER, null, [ 'identity' => true, 'nullable' => false, 'primary' => true, 'unsigned' => true, ], 'Entity ID') ->addColumn('product_id', Table::TYPE_INTEGER, null, [ 'unsigned' => true, 'nullable' => false, ], 'Product ID') ->addColumn('custom_value', Table::TYPE_DECIMAL, '12,4', [ 'nullable' => false, 'default' => '0.0000', ], 'Custom Value') ->addColumn('status', Table::TYPE_SMALLINT, null, [ 'nullable' => false, 'default' => 1, ], 'Status') ->addColumn('created_at', Table::TYPE_TIMESTAMP, null, [ 'nullable' => false, 'default' => Table::TIMESTAMP_INIT, ], 'Created At') ->addColumn('updated_at', Table::TYPE_TIMESTAMP, null, [ 'nullable' => false, 'default' => Table::TIMESTAMP_INIT_UPDATE, ], 'Updated At') ->addForeignKey( $setup->getFkName($tableName, 'product_id', 'catalog_product_entity', 'entity_id'), 'product_id', $setup->getTable('catalog_product_entity'), 'entity_id', Table::ACTION_CASCADE ) ->addIndex($setup->getIdxName($tableName, ['status']), ['status']) ->setComment('Vendor Custom Entity Table'); $connection->createTable($table); } $setup->endSetup(); } public static function getDependencies(): array { return []; } public function getAliases(): array { return []; } } 

Шаг 3: Observer и Plugin — реакции на события

Типичная задача — при создании заказа записывать дополнительную информацию в кастомную таблицу. Используем Observer на событие sales_order_place_after:

<?php // Observer/OrderPlaceAfter.php namespace Vendor\Module\Observer; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; use Psr\Log\LoggerInterface; class OrderPlaceAfter implements ObserverInterface { public function __construct( private readonly LoggerInterface $logger, private readonly \Vendor\Module\Model\CustomEntityFactory $entityFactory, private readonly \Vendor\Module\Model\ResourceModel\CustomEntity $entityResource, ) {} public function execute(Observer $observer): void { /** @var \Magento\Sales\Model\Order $order */ $order = $observer->getEvent()->getOrder(); try { foreach ($order->getAllVisibleItems() as $item) { $entity = $this->entityFactory->create(); $entity->setData([ 'product_id' => (int)$item->getProductId(), 'custom_value' => $item->getQtyOrdered(), 'status' => 1, ]); $this->entityResource->save($entity); } } catch (\Exception $e) { $this->logger->error('OrderPlaceAfter observer error: ' . $e->getMessage(), [ 'order_id' => $order->getId(), ]); } } } 

Для изменения поведения существующих классов используем Plugin (Interceptor). Например, подставляем дефолтное значение для кастомного поля перед сохранением продукта:

<?php // Plugin/ProductSavePlugin.php namespace Vendor\Module\Plugin; use Magento\Catalog\Model\Product; class ProductSavePlugin { public function beforeSave(Product $subject): void { if (!$subject->getData('custom_field')) { $subject->setData('custom_field', 'default_value'); } } public function afterSave(Product $subject, Product $result): Product { // Инвалидация кастомного кеша при сохранении продукта return $result; } } 

Почему Plugin лучше Preference?

Plugin позволяет модифицировать только конкретные методы, не переопределяя весь класс. Это уменьшает объём кода на 40% и снижает риск конфликтов с другими модулями. Preference же заменяет класс целиком, что может вызвать проблемы при наличии нескольких переопределений. Magento DevDocs: "Plugins are the primary way to extend Magento's behavior."

Характеристика Plugin Observer Preference
Область Конкретный метод Событие Весь класс
Гибкость Высокая (before/after/around) Средняя (только after) Низкая (полная замена)
Производительность Высокая (только при вызове) Средняя (всегда загружается) Высокая
Конфликты Минимальные Низкие Высокие

Как тестировать модуль Magento 2?

Тестирование — обязательный этап. Unit-тесты проверяют логику изолированно, Integration-тесты — работу с базой и внешними сервисами. Мы покрываем тестами не менее 70% кода. Это предотвращает регрессию и повышает надёжность модуля. Используйте PHPUnit и Magento Testing Framework.

Типичные ошибки при разработке модулей Magento 2
  • Неправильная последовательность модулей (sequence) — приводит к ошибкам при установке.
  • Игнорирование Core Web Vitals и производительности — например, N+1 запросы через цикл в Observer.
  • Использование around-плагинов без необходимости — они увеличивают сложность на 30%.
  • Отсутствие тестов — модуль становится чёрным ящиком.
  • Хранение конфиденциальных данных в коде — используйте config.php или переменные окружения.

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

Мы разрабатываем кастомный модуль под ключ:

  • Декларация модуля, composer.json, registration.php.
  • Setup Patches для схемы и данных.
  • API интерфейсы и Repository pattern для работы с сущностями.
  • Observer и Plugin для интеграции с событиями Magento.
  • Admin Grids и формы для управления данными.
  • Unit и Integration тесты для покрытия логики (не менее 70% строк).
  • Документация: описание функционала, инструкция по установке.
  • Передача доступов к репозиторию и сопровождение.
Тип модуля Примерный срок Что входит
Простой 3–5 дней Таблица, CRUD, Observer, базовый Admin Grid
Средний 1–2 недели Repository, REST API, тесты, полноценный Admin
Сложный 3–6 недель Внешняя интеграция, очереди, GraphQL, боевое тестирование

Кейс: синхронизация заказов с ERP

Из нашей практики: к нам обратился клиент — интернет-магазин с 5000 заказов в день. Требовалось передавать данные в их учётную систему без ручного дублирования. Мы разработали модуль с Observer на sales_order_place_after, который записывал данные в кастомную таблицу, и Console Command для фоновой отправки. Использовали Plugin для добавления статуса передачи в админке. Решение прошло нагрузку 1000+ заказов в час без сбоев, сократив трудозатраты на 80%. Экономия составила значительную сумму. Если вам нужна аналогичная интеграция — обращайтесь, мы проконсультируем.

Сроки и ориентировочная стоимость

Сроки варьируются: простой модуль — от 3 до 5 дней, средний — 1–2 недели, сложный — 3–6 недель. Стоимость рассчитывается индивидуально после анализа требований. Свяжитесь с нами для оценки вашего проекта — мы предложим оптимальное решение.

Мы работаем с Magento более 5 лет, реализовали 50+ кастомных модулей для разных задач. Наши разработчики сертифицированы и владеют полным стеком Magento 2. Гарантируем качество и соблюдение сроков. Получите консультацию по разработке кастомного модуля Magento 2 — заполните форму обратной связи, и мы свяжемся с вами в течение дня.