Статті та новини
Як правильно оформляти модулі для OpenCart 3

Модуль для OpenCart 3 - це не лише робоча функціональність, а й грамотний підхід до опису та підтримки. Бідний опис може відлякати покупців, а правильний стиль оформлення підвищує довіру та полегшує роботу з вашим продуктом.

 
 
 
 
 
Як правильно створювати модулі для OpenCart 3

Добре зроблений модуль для OpenCart 3 - це чистий і структурований код з єдиним стилем. Це зменшує кількість запитань, підвищує довіру та допомагає ефективніше продавати модуль.

 
 
 
 
 
Підбірка нових модулів для OpenCart за серпень 2025

Новинки за серпень 2025 року: Підтвердження e-mail та підписки, Захист адмін-панелі, Модуль коротких посилань, Доставка залежно від відстані в межах області.

 
 
 
 
 
Хостинг для вашего интернет-магазина

Найбільш продавані шаблони та доповнення у серпні 2025 року: фільтр товарів Dream Filter, Strizh: вхід через соцмережі, Telegram сповіщення, шаблон Dynamic Color.

 
 
 
 
 
Найбільш продавані шаблони та доповнення у серпні 2025 року

Найбільш продавані шаблони та доповнення у серпні 2025 року: фільтр товарів Dream Filter, Strizh: вхід через соцмережі, Telegram сповіщення, шаблон Dynamic Color.

 
 
 
 
 

Як правильно створювати модулі для OpenCart 3

 
Як правильно створювати модулі для OpenCart 3
  • 09 сентября 2025
  • Комментарии :2
  • Просмотров: 702

OpenCart 3 үшін жақсы жасалған модуль - біртекті стильдегі таза әрі құрылымды код.

Бұл сұрақтардың санын азайтады, сенімді арттырады және модульді тиімдірек сатуға көмектеседі.

Модуль для OpenCart 3 - це не лише робоча функціональність, а й грамотний підхід до коду та структури. Непродуманий код може відлякати покупців, а правильний стиль розробки підвищує довіру і полегшує роботу з вашим продуктом. Нижче буде кілька порад, можливо вони допоможуть вам у розробці. Якщо хочете щось додати або змінити в тексті - пишіть у коментарях або на пошту.

Стиль написання коду модуля

Цей розділ задає загальний підхід до оформлення коду та спільні очікування для команди. Простi правила підвищують читабельність і знижують вартість підтримки.

Єдиний синтаксис

Тут зібрані короткі та перевірювані правила форматування і найменування. Вони допомагають тримати код в одному стилі.

  • Відступи - використовуйте 4 пробіли, уникайте табуляції.
  • Фігурні дужки - ставте відкривну в тій же стрічці, що й конструкція (if, foreach, function).
  • Пробіли - додавайте пробіли навколо операторів (=, ==, +, .) і після ком.
  • Найменування - класи в CamelCase, змінні та ключі масивів у snake_case.
 class ControllerExtensionModuleLiveExample extends Controller { public function index() { $this->load->language('extension/module/live_example');
    $data['example_status'] = $this->config->get('module_live_example_status');
    
    if ($data['example_status']) {
        return $this->load->view('extension/module/live_example', $data);
    }
}


}

Структура коду

Визначаємо де зберігати логіку, дані та подання. Чітка структура робить проєкт передбачуваним і зручним для доробок.

  • Контролери - тонкі, вся бізнес логіка має бути в моделях.
  • Валідація та перевірки - виконуються в моделі, а не в шаблонах.
  • Мовні файли - ніякого тексту в коді і шаблонах, все в language/.
  • Twig шаблони - використовуйте нативний синтаксис ({{ variable }}, {% if %}), не PHP.

Розподіл обов'язків: модель, контролер, бібліотека

Позначаємо ролі основних шарів. Чіткі межі спрощують тестування та повторне використання.

Модель

Завдання: робота з базою даних, SQL запити та повернення даних.

 public function getCustomerByEmail($email) { $sql = "SELECT * FROM " . DB_PREFIX . "customer WHERE email = '" . $this->db->escape($email) . "'"; $query = $this->db->query($sql); return $query->row; } 

Контролер

Завдання: робота з $this->request, виклик моделей, формування $this->response. У контролері не має бути SQL і складної бізнес логіки.

 public function getCustomer() { $this->load->model('account/customer');
$email = $this->request->get['email'];
$customer = $this->model_account_customer->getCustomerByEmail($email);

$this->response->setOutput(json_encode($customer));


}

Бібліотека

Завдання: зберігати бізнес логіку модуля, яку можна використовувати з різних місць (фронт, адмін, cron).

 class Bonus { public function calculate($order_total) { return floor($order_total * 0.05); } } 

Переваги розподілу

  • Підтримуваність - зміни простіше вносити: SQL у моделях, логіка в бібліотеках, відповіді в контролерах.
  • Тестованість - можна окремо тестувати модель (SQL), бібліотеку (логіка), контролер (API).
  • Повторне використання - бібліотеки можна підключати у фронті, в адмінці та у CRON.

Сумісність і безпека

Збираємо базові практики захисту та перевірки сумісності. Ці кроки знижують ризики і подовжують життя коду.

  • Використовуйте $this->db->escape() і (int) для SQL запитів.
  • Застосовуйте htmlspecialchars або html_entity_decode при виведенні.
  • Уникайте застарілих функцій (mysql_*, ereg, split).
  • Для рядків використовуйте mb_*.
  • Перевіряйте роботу на актуальних версіях PHP (7.4, 8.0, 8.1, 8.2).

Екранування вхідних даних

Показуємо як безпечно приймати дані і готувати запити. Приклади можна одразу вставити в робочий код.

Неправильно (параметри з request прямо в SQL):

 $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "customer WHERE email = '" . $this->request->post['email'] . "'"); 

Якщо зловмисник введе ' OR 1=1 --, запит поверне всіх користувачів.

Правильно (контролер валідовує, модель працює з аргументами):

Контролер:

 public function info() { // 1) отримуємо і валідовуємо email $email = trim($this->request->post['email'] ?? ''); if (!filter_var($email, FILTER_VALIDATE_EMAIL) || mb_strlen($email) > 96) { $this->response->addHeader('Content-Type: application/json'); $this->response->setOutput(json_encode(['error' => 'Некоректний email'])); return; }
// 2) працюємо через модель
$this->load->model('account/customer');
$customer = $this->model_account_customer->getCustomerByEmail($email);

$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($customer));


}

Модель:

 public function getCustomerByEmail($email) { $email = $this->db->escape($email);
$query = $this->db->query(
    "SELECT * FROM " . DB_PREFIX . "customer WHERE email = '" . $email . "'"
);

return $query->row;


}

Для числових значень використовуйте явне приведення і просту валідацію:

Контролер:

 $order_id = (int)($this->request->get['order_id'] ?? 0); if ($order_id <= 0) { $this->response->addHeader('Content-Type: application/json'); $this->response->setOutput(json_encode(['error' => 'Некоректний order_id'])); return; }

$this->load->model('account/order');
$order_info = $this->model_account_order->getOrder($order_id);

$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($order_info));

Модель:

 public function getOrder($order_id) { $query = $this->db->query( "SELECT * FROM " . DB_PREFIX . "order WHERE order_id = " . (int)$order_id ); return $query->row; } 

Золоте правило: рядки через $this->db->escape(), числа через (int) або (float). Не використовуйте $this->request всередині моделі.

Розбиття SQL запиту построково

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

Для коротких запитів можна використовувати один рядок:

 $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "customer WHERE customer_id = " . (int)$customer_id); 

Але для довгих запитів рекомендується багаторядковий формат:

$query = $this->db->query("
    SELECT p.product_id, p.model, pd.name, p.price 
    FROM " . DB_PREFIX . "product p
    LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)
    LEFT JOIN " . DB_PREFIX . "product_to_category p2c ON (p.product_id = p2c.product_id)
    WHERE pd.language_id = " . (int)$this->config->get('config_language_id') . "
      AND p.status = '1'
      AND p.date_available <= NOW()
    ORDER BY p.date_added DESC
    LIMIT 20
");
  • Чітко видно структуру запиту: SELECT, FROM, JOIN, WHERE, ORDER BY.
  • Легше додавати нові умови без втрати читабельності.
  • Простіше знаходити помилки SQL.
  • Єдиний стиль для всіх розробників у команді.

Підключення власних бібліотек

Розбираємо варіанти підключення власних класів. Вибір залежить від того, де потрібен об'єкт і коли краще його ініціалізувати.

1. Через реєстр у catalog/startup/startup.php

Підходить, якщо бібліотека має бути доступна глобально на фронті одразу після старту.

  1. Покладіть файл бібліотеки в system/library/MyLib.php або catalog/library/MyLib.php.
  2. Усередині catalog/controller/startup/startup.php додайте реєстрацію:
 // Якщо бібліотека в system/library: // $this->load->library('mylib'); // $this->registry->set('mylib', $this->mylib);

// Якщо бібліотека в catalog/library:
require_once(modification(DIR_CATALOG . 'library/mylib.php'));
$this->registry->set('mylib', new MyLib($this->registry));

Плюси: єдина точка ініціалізації, доступність всюди. Мінуси: об'єкт створюється на кожен запит, навіть якщо не використовується.

2. Локально через require modification(...) у місці використання

Підходить для ледачого підключення лише там, де справді потрібно.

 require_once(modification(DIR_SYSTEM . 'library/mylib.php'));

$mylib = new MyLib($this->registry);
$result = $mylib->doWork($params);

Плюси: підключення за потребою. Мінуси: підключення доведеться повторювати або винести в helper.

3. Через завантажувач OpenCart: $this->load->library()

Стандартний спосіб, якщо бібліотека знаходиться в system/library.

 $this->load->library('mylib'); // шукає system/library/mylib.php $this->mylib->doWork($params); // об'єкт доступний як $this->mylib 

Рекомендація: якщо бібліотека лежить у system/library - використовуйте $this->load->library(). Якщо потрібна рання глобальна ініціалізація - реєстрація в startup.php. Якщо бібліотека в іншому каталозі - підключайте через require modification(...).

Коментарі

Коментарі доповнюють код і пояснюють намір. Короткі та точні описи економлять час на читання.

 /** * Отримання списку товарів для прикладу * * @param int $limit Кількість товарів * @return array Список товарів */ public function getProducts($limit = 10) { $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product LIMIT " . (int)$limit); return $query->rows; } 

Дайте можливість покупцю бачити версію вашого модуля

Версія слугує орієнтиром для оновлень і підтримки. Прозорість зменшує кількість звернень у підтримку.

Показуйте номер версії в налаштуваннях модуля. Це спрощує підтримку і усуває плутанину.

  1. В контролері адмінки збережіть номер версії і передайте його в шаблон:
 class ControllerExtensionModuleMyModule extends Controller { private $module_version = '1.0.0';
public function index() {
    // ... ваша логіка
    $data['module_version'] = $this->module_version;
    return $this->load->view('extension/module/my_module', $data);
}


}
  1. У шаблоні адмінки виведіть значення:
 <div class="text-muted">Версія модуля: {{ module_version }}</div> 

Порада: номер версії має збігатися з версією в архіві та в CHANGELOG, щоб клієнт завжди бачив актуальну інформацію.

Добре зроблений модуль для OpenCart 3 - це чистий і структурований код з єдиним стилем.

Це зменшує кількість запитань, підвищує довіру і допомагає ефективніше продавати модуль.


Рекомендуем прочитать