Модуль для OpenCart 3 - це не лише робоча функціональність, а й грамотний підхід до опису та підтримки. Бідний опис може відлякати покупців, а правильний стиль оформлення підвищує довіру та полегшує роботу з вашим продуктом.
→Добре зроблений модуль для OpenCart 3 - це чистий і структурований код з єдиним стилем. Це зменшує кількість запитань, підвищує довіру та допомагає ефективніше продавати модуль.
→Новинки за серпень 2025 року: Підтвердження e-mail та підписки, Захист адмін-панелі, Модуль коротких посилань, Доставка залежно від відстані в межах області.
→Найбільш продавані шаблони та доповнення у серпні 2025 року: фільтр товарів Dream Filter, Strizh: вхід через соцмережі, Telegram сповіщення, шаблон Dynamic Color.
→Найбільш продавані шаблони та доповнення у серпні 2025 року: фільтр товарів Dream Filter, Strizh: вхід через соцмережі, Telegram сповіщення, шаблон Dynamic Color.
→OpenCart 3 үшін жақсы жасалған модуль - біртекті стильдегі таза әрі құрылымды код.
Бұл сұрақтардың санын азайтады, сенімді арттырады және модульді тиімдірек сатуға көмектеседі.
Модуль для OpenCart 3 - це не лише робоча функціональність, а й грамотний підхід до коду та структури. Непродуманий код може відлякати покупців, а правильний стиль розробки підвищує довіру і полегшує роботу з вашим продуктом. Нижче буде кілька порад, можливо вони допоможуть вам у розробці. Якщо хочете щось додати або змінити в тексті - пишіть у коментарях або на пошту.
Цей розділ задає загальний підхід до оформлення коду та спільні очікування для команди. Простi правила підвищують читабельність і знижують вартість підтримки.
Тут зібрані короткі та перевірювані правила форматування і найменування. Вони допомагають тримати код в одному стилі.
if
, foreach
, function
).=
, ==
, +
, .
) і після ком.
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/
.{{ 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); } }
Переваги розподілу
Збираємо базові практики захисту та перевірки сумісності. Ці кроки знижують ризики і подовжують життя коду.
$this->db->escape()
і (int)
для SQL запитів.htmlspecialchars
або html_entity_decode
при виведенні.mysql_*
, ereg
, split
).mb_*
.Показуємо як безпечно приймати дані і готувати запити. Приклади можна одразу вставити в робочий код.
Неправильно (параметри з 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
всередині моделі.
Показуємо як оформляти запити так, щоб їх було зручно читати і розширювати. Єдиний стиль пришвидшує рев'ю і зменшує кількість помилок.
Для коротких запитів можна використовувати один рядок:
$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
");
Розбираємо варіанти підключення власних класів. Вибір залежить від того, де потрібен об'єкт і коли краще його ініціалізувати.
1. Через реєстр у catalog/startup/startup.php
Підходить, якщо бібліотека має бути доступна глобально на фронті одразу після старту.
system/library/MyLib.php
або catalog/library/MyLib.php
.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; }
Версія слугує орієнтиром для оновлень і підтримки. Прозорість зменшує кількість звернень у підтримку.
Показуйте номер версії в налаштуваннях модуля. Це спрощує підтримку і усуває плутанину.
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);
}
}
<div class="text-muted">Версія модуля: {{ module_version }}</div>
Порада: номер версії має збігатися з версією в архіві та в CHANGELOG, щоб клієнт завжди бачив актуальну інформацію.
Добре зроблений модуль для OpenCart 3 - це чистий і структурований код з єдиним стилем.
Це зменшує кількість запитань, підвищує довіру і допомагає ефективніше продавати модуль.