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

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

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

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка кастомного модуля PrestaShop
Середня
~3-5 робочих днів
Часті питання

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

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

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

Модуль — основна одиниця розширення PrestaShop. Через модулі реалізується будь-яка кастомна логіка: від кастомних полів замовлення до інтеграцій із зовнішніми API. Модуль може реєструвати хуки, додавати контролери, розширювати схему БД, додавати віджети в back-office через Symfony DI.

Структура модуля

modules/mymodule/
├── mymodule.php             # Головний клас модуля
├── config.xml               # Метадані (опціонально)
├── composer.json            # Залежності (опціонально)
├── logo.png                 # Іконка 32x32
├── controllers/
│   └── front/
│       └── callback.php     # FrontController: /module/mymodule/callback
├── src/                     # PSR-4 namespace класи
│   ├── Entity/
│   ├── Repository/
│   └── Service/
├── views/
│   └── templates/
│       ├── admin/
│       │   └── configure.html.twig
│       └── hook/
│           └── display_banner.tpl
├── translations/            # Переводи модуля
└── upgrade/                 # SQL-міграції при оновленні
    └── upgrade-1.1.0.php

Головний клас та життєвий цикл

<?php
declare(strict_types=1);

use PrestaShop\PrestaShop\Adapter\SymfonyContainer;

if (!defined('_PS_VERSION_')) {
    exit;
}

class MyModule extends Module
{
    public function __construct()
    {
        $this->name    = 'mymodule';
        $this->tab     = 'other';
        $this->version = '1.2.0';
        $this->author  = 'Company Name';
        $this->need_instance     = 0;
        $this->bootstrap         = true;
        $this->ps_versions_compliancy = ['min' => '8.0.0', 'max' => _PS_VERSION_];

        parent::__construct();

        $this->displayName = $this->trans('My Module', [], 'Modules.Mymodule.Admin');
        $this->description = $this->trans('Module description', [], 'Modules.Mymodule.Admin');
    }

    public function install(): bool
    {
        return parent::install()
            && $this->installDb()
            && $this->registerHook('actionOrderStatusPostUpdate')
            && $this->registerHook('displayCustomerAccount')
            && $this->registerHook('displayHeader');
    }

    public function uninstall(): bool
    {
        return parent::uninstall() && $this->uninstallDb();
    }

    private function installDb(): bool
    {
        $sql = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'mymodule_data` (
            `id_mymodule` INT UNSIGNED NOT NULL AUTO_INCREMENT,
            `id_order`    INT UNSIGNED NOT NULL,
            `payload`     TEXT,
            `status`      TINYINT(1) NOT NULL DEFAULT 0,
            `date_add`    DATETIME NOT NULL,
            PRIMARY KEY (`id_mymodule`),
            KEY `id_order` (`id_order`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;';

        return Db::getInstance()->execute($sql);
    }
}

Робота з хуками

Хуки бувають двох типів: action (змінюють поведінку, повертають дані) та display (повертають HTML). Важливо розрізняти:

// Display hook — повертає HTML-рядок
public function hookDisplayCustomerAccount(array $params): string
{
    $customerId = (int) $this->context->customer->id;
    $data = $this->getCustomerData($customerId);

    if (empty($data)) {
        return '';
    }

    $this->smarty->assign([
        'mymodule_data' => $data,
        'moduleUrl'     => $this->context->link->getModuleLink('mymodule', 'account'),
    ]);

    return $this->display(__FILE__, 'views/templates/hook/customer_account.tpl');
}

// Action hook — модифікує дані або виконує side-effect
public function hookActionOrderStatusPostUpdate(array $params): void
{
    /** @var Order $order */
    $order  = $params['order'];
    $newStatus = $params['newOrderStatus'];

    if ((int) $newStatus->id === (int) Configuration::get('PS_OS_PAYMENT')) {
        $this->notifyExternalSystem($order);
    }
}

Symfony DI та сучасний back-office

PrestaShop 8.x дозволяє використовувати Symfony DI в модулях через config/services.yml:

# modules/mymodule/config/services.yml
services:
  _defaults:
    autowire: true
    autoconfigure: true
    public: true

  MyModule\Repository\OrderDataRepository:
    arguments:
      $connection: '@doctrine.dbal.default_connection'

  MyModule\Service\ExternalApiService:
    arguments:
      $apiKey: '%env(MYMODULE_API_KEY)%'
      $logger: '@logger'

Використання у контролері back-office (Symfony-style):

// src/Controller/Admin/OrderDataController.php
namespace MyModule\Controller\Admin;

use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
use Symfony\Component\HttpFoundation\JsonResponse;
use MyModule\Repository\OrderDataRepository;

class OrderDataController extends FrameworkBundleAdminController
{
    public function __construct(
        private readonly OrderDataRepository $repository
    ) {}

    public function indexAction(int $orderId): JsonResponse
    {
        $data = $this->repository->findByOrderId($orderId);

        return $this->json([
            'success' => true,
            'data'    => $data,
        ]);
    }
}

Міграції схеми БД

При оновленні модуля використовуйте upgrade-скрипти:

// modules/mymodule/upgrade/upgrade-1.2.0.php
function upgrade_module_1_2_0(Module $module): bool
{
    $result = Db::getInstance()->execute(
        'ALTER TABLE `' . _DB_PREFIX_ . 'mymodule_data`
         ADD COLUMN `external_id` VARCHAR(128) NULL AFTER `id_order`,
         ADD INDEX `external_id` (`external_id`)'
    );

    if ($result) {
        // Міграція даних
        Db::getInstance()->execute(
            'UPDATE `' . _DB_PREFIX_ . 'mymodule_data` SET `status` = 1 WHERE `status` = 0 AND `date_add` < NOW()'
        );
    }

    return (bool) $result;
}

Локалізація модуля

PrestaShop використовує Symfony Translation для back-office та власний механізм для front-office:

// Back-office (Symfony Translation)
$this->trans('Order processed', [], 'Modules.Mymodule.Admin');

// Front-office (Smarty)
// У .tpl файлі:
// {l s='Order processed' mod='mymodule'}

// Генерація файлів переводів
php bin/console prestashop:generate:translations --module=mymodule

Тестування модуля

// tests/Unit/Service/ExternalApiServiceTest.php
use PHPUnit\Framework\TestCase;
use MyModule\Service\ExternalApiService;

class ExternalApiServiceTest extends TestCase
{
    public function testNotifyOrder(): void
    {
        $httpClient = $this->createMock(HttpClientInterface::class);
        $httpClient->expects($this->once())
            ->method('request')
            ->with('POST', 'https://api.example.com/orders')
            ->willReturn(new MockResponse('{"status":"ok"}', ['http_code' => 200]));

        $service = new ExternalApiService($httpClient, 'test-api-key');
        $result  = $service->notifyOrderPaid(12345);

        $this->assertTrue($result);
    }
}

Терміни розробки

  • Простий модуль: хуки, конфігурація, вивід даних: 2–4 дні
  • Інтеграція із зовнішнім API (платіжна система, CRM): 5–10 днів
  • Модуль із кастомними сутностями, CRUD у back-office, міграціями: 7–14 днів
  • Складний модуль (кастомний checkout, програма лояльності): 3–6 тижнів