Як створити власний плагін в OpenCart 2.1.x.x: частина 1

314

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

У першому уроці ми створимо власний плагін, який буде показувати нещодавно переглянуті товари на стороні back-end’а. Змінити кількість товарів можна на стороні back-end’а. Мета сьогоднішнього уроку – розробити back-end плагін з формою конфігурацій.

Передбачається, що у вас вже встановлена остання версія OpenCart. На момент написання статті це була версія 2.1.0.2. Перед самою розробкою плагіна я хочу розповісти вам про базову архітектуру плагінів в OpenCart.

Коротко про шаблоні MVCL

OpenCart спроектований по одному із самих популярних шаблонів веб-розробки MVC з невеликими змінами або, можна сказати, доповненнями. Це додаток перетворює шаблон в MVCL. Можливо, ви вже чули про даному шаблоні, але я все одно швидко пробегусь по ньому для новачків.

Буква M в MVC розшифровується як модель, саме там розташована майже вся логіка. У контексті OpenCart модель взаємодіє з абстрактним шаром бази даних і виконує всю важку роботу, необхідну для роботи магазину. Велику частину часу ви будете проводити в моделі.

Як створити власний плагін в OpenCart 2.1.x.x: частина 1

Інтернет-магазин на OpenCart!

Створити інтернет-магазин на самій популярної CMS OpenCart з нуля!

Приступити до створення

V розшифровується як подання – шар подання додатка. З назви зрозуміло, що даний шар працює тільки з логікою подання сторінок, отримує дані від інших верств і велику частину часу генерує XHTML вихідні дані. Програмний код в цьому шарі краще не писати. Подання має дбати лише про те, що робити, а не як це робити.

C – контролер MVC, обробляє всі запити. Цей шар охоплює більшу частину логіки додатка: від обробки та валідації даних, що вводяться до завантаження відповідної моделі та виду для підготовки сторінки на висновок.
Нарешті, є додатковий компонент L, який розшифровується як мова. З його допомогою набагато легше створювати багатомовні сайти.

Це був швидкий огляд архітектури OpenCart. Як тільки ми почнемо більш докладно розбирати всі компоненти, вам стане все набагато зрозуміліше.

Скелет кожного плагіна в OpenCart

Давайте поглянемо на те, які файли нам знадобляться для створення користувальницького back-end плагіна.

admin/language/english/module/recent_products.php: файл, в якому зберігаються статичні назви, які використовуються в адмінці.

admin/controller/module/recent_products.php: файл контролера, в якому зберігається логіка програми нашого модуля.

admin/view/template/module/recent_products.tpl: файл-шаблон подання з XHTML кодом.

В наступній секції ми створимо всі ці файли і детально їх розглянемо. Згідно з оголошенням вище, файли інтерфейсу плагіна повинні бути в папці module. Так як це back-end плагін, то цю папку потрібно шукати в папці admin. У відповідності з архітектурою, описаної вище, всі файли розкидані по різних каталогах або компонентів.

Створюємо файли для back-end плагіна

У цьому розділі ми будемо створювати файли модуля. Першим ми створимо файл мови admin/language/english/module/recent_products.php з таким кодом. Вкрай важливий файл, так як OpenCart повинен знайти його в вашому плагіні.

З коду видно, що статичні лейбли занесені в PHP масив. Пізніше, коли масив буде переконвертовано в PHP змінні, вони стануть доступні в шаблоні подання.

Також ви могли звернути увагу, що файл був створений у папці english – це папка з мовою за промовчанням для магазину. Якщо у вас багатомовний сайт, необхідно буде створити додаткові папки. Наприклад, для французького необхідно буде створити файл у папці admin/language/french/module/recent_products.php.

Далі ми створимо один з найважливіших файлів плагіна – файл контролера. Створіть файл admin/controller/module/recent_products.php з кодом нижче.

load->language(‘module/recent_products’);
$this->document->setTitle($this->language->get(‘heading_title’));
$this->load->model(‘extension/module’);
if (( $this->request->server[‘REQUEST_METHOD’] == ‘POST’ ) && $this->validate()) {
if (!isset( $this->request->get[‘module_id’] )) {
$this->model_extension_module->addModule( ‘recent_products’, $this->request->post );
} else {
$this->model_extension_module->editModule( $this->request->get[‘module_id’], $this->request->post );
}
$this->session->data[‘success’] = $this->language->get(‘text_success’);
$this->response->redirect( $this->url->link( ‘extension/module’, ‘token=’ . $this->session->data[‘token’], ‘SSL’ ) );
}
$data[‘heading_title’] = $this->language->get(‘heading_title’);
$data[‘text_edit’] = $this->language->get(‘text_edit’);
$data[‘text_enabled’] = $this->language->get(‘text_enabled’);
$data[‘text_disabled’] = $this->language->get(‘text_disabled’);
$data[‘entry_name’] = $this->language->get(‘entry_name’);
$data[‘entry_limit’] = $this->language->get(‘entry_limit’);
$data[‘entry_status’] = $this->language->get(‘entry_status’);
$data[‘button_save’] = $this->language->get(‘button_save’);
$data[‘button_cancel’] = $this->language->get(‘button_cancel’);
if (isset($this->error[‘warning’])) {
$data[‘error_warning’] = $this->error[‘warning’];
} else {
$data[‘error_warning’] = “;
}
if (isset($this->error[‘name’])) {
$data[‘error_name’] = $this->error[‘name’];
} else {
$data[‘error_name’] = “;
}
$data[‘breadcrumbs’] = array();
$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘text_home’),
‘href’ => $this->url->link( ‘common/dashboard’, ‘token=’ . $this->session->data[‘token’], ‘SSL’ )
);
$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘text_module’),
‘href’ => $this->url->link( ‘extension/module’, ‘token=’ . $this->session->data[‘token’], ‘SSL’ )
);
if (!isset($this->request->get[‘module_id’])) {
$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘heading_title’),
‘href’ => $this->url->link( ‘module/recent_products’, ‘token=’ . $this->session->data[‘token’], ‘SSL’ )
);
} else {
$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘heading_title’),
‘href’ => $this->url->link( ‘module/recent_products’, ‘token=’ . $this->session->data[‘token’] . ‘&module_id=’ . $this->request->get[‘module_id’], ‘SSL’ )
);
}
if (!isset($this->request->get[‘module_id’])) {
$data[‘action’] = $this->url->link( ‘module/recent_products’, ‘token=’ . $this->session->data[‘token’], ‘SSL’ );
} else {
$data[‘action’] = $this->url->link( ‘module/recent_products’, ‘token=’ . $this->session->data[‘token’] . ‘&module_id=’ . $this->request->get[‘module_id’], ‘SSL’ );
}
$data[‘cancel’] = $this->url->link( ‘extension/module’, ‘token=’ . $this->session->data[‘token’], ‘SSL’ );
if (isset( $this->request->get[‘module_id’]) && ( $this->request->server[‘REQUEST_METHOD’] != ‘POST’ ) ) {
$module_info = $this->model_extension_module->getModule( $this->request->get[‘module_id’] );
}
if (isset($this->request->post[‘name’])) {
$data[‘name’] = $this->request->post[‘name’];
} elseif (!empty($module_info)) {
$data[‘name’] = $module_info[‘name’];
} else {
$data[‘name’] = “;
}
if (isset($this->request->post[‘limit’])) {
$data[‘limit’] = $this->request->post[‘limit’];
} elseif (!empty($module_info)) {
$data[‘limit’] = $module_info[‘limit’];
} else {
$data[‘limit’] = 5;
}
if (isset($this->request->post[‘status’])) {
$data[‘status’] = $this->request->post[‘status’];
} elseif (!empty($module_info)) {
$data[‘status’] = $module_info[‘status’];
} else {
$data[‘status’] = “;
}
$data[‘header’] = $this->load->controller(‘common/header’);
$data[‘column_left’] = $this->load->controller(‘common/column_left’);
$data[‘footer’] = $this->load->controller(‘common/footer’);
$this->response->setOutput( $this->load->view( ‘module/recent_products.tpl’, $data ) );
}
protected function validate() {
if ( !$this->user->hasPermission( ‘змінити’, ‘module/recent_products’ ) ) {
$this->error[‘warning’] = $this->language->get(‘error_permission’);
}
if ((utf8_strlen($this->request->post[‘name’]) request->post[‘name’]) > 64)) {
$this->error[‘name’] = $this->language->get(‘error_name’);
}
return !$this->error;
}
}

У коді створюється новий клас для плагіна, який є дочірнім для базового класу Controller. Судячи з кодом, назва класу повинно дублювати структуру папок до цього файлу. Шлях controller/module/recent_products.php перетворюється в ControllerModuleRecentProducts (опускаємо слеш, а перші літери записуємо у верхньому регістрі).

Далі йде метод за замовчуванням index, який викликається відразу після завантаження плагіна на стороні front-end’а. У цьому методі прописана основна логіка плагіна.

У контексті поточного додатка скорочення $this->load->language завантажує відповідний файл мови. У нашому випадку завантажується файл, вказаний у попередньому розділі. Синтаксис досить простий – потрібно передати назву плагіна з префіксом module/. Змінні мови доступні через метод $this->language->get. Далі задається заголовок сторінки за допомогою методу setTitle об’єкта document.

Як створити власний плагін в OpenCart 2.1.x.x: частина 1

Інтернет-магазин на OpenCart!

Створити інтернет-магазин на самій популярної CMS OpenCart з нуля!

Приступити до створення

Йдемо далі, скорочення $this->load->model використовується для завантаження моделі модуля. Модель являє собою клас з методами, за допомогою яких можна зберігати параметри модуля.

Далі йде важливий шматок коду, який перевіряє, щоб дані були подані в POST форматі. Якщо все правильно, за умовою зберігаються настройки модуля.

if (($this->request->server[‘REQUEST_METHOD’] == ‘POST’) && $this->validate()) {
if (!isset($this->request->get[‘module_id’])) {
$this->model_extension_module->addModule( ‘recent_products’, $this->request->post );
} else {
$this->model_extension_module->editModule( $this->request->get[‘module_id’], $this->request->post );
}
$this->session->data[‘success’] = $this->language->get(‘text_success’);
$this->response->redirect( $this->url->link( ‘extension/module’, ‘token=’ . $this->session->data[‘token’], ‘SSL’ ) );
}

Далі ми записуємо мовні лейбли типу heading_title і text_edit в масив $data, щоб потім використовувати їх у файлі шаблону. Слідом йде шматок коду, який відповідає за створення хлібних крихт на сторінці налаштувань.

$data[‘breadcrumbs’] = array();
$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘text_home’),
‘href’ => $this->url->link( ‘common/dashboard’, ‘token=’ . $this->session->data[‘token’], ‘SSL’ )
);
$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘text_module’),
‘href’ => $this->url->link( ‘extension/module’, ‘token=’ . $this->session->data[‘token’], ‘SSL’ )
);
if (!isset($this->request->get[‘module_id’])) {
$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘heading_title’),
‘href’ => $this->url->link( ‘module/recent_products’, ‘token=’ . $this->session->data[‘token’], ‘SSL’ )
);
} else {
$data[‘breadcrumbs’][] = array(
‘text’ => $this->language->get(‘heading_title’),
‘href’ => $this->url->link( ‘module/recent_products’, ‘token=’ . $this->session->data[‘token’] . ‘&module_id=’ . $this->request->get[‘module_id’], ‘SSL’ )
);
}

Якби модуль вже був налаштований і знаходився в режимі редагування, наступний шматок коду виставив би налаштування за замовчуванням.

if ( isset( $this->request->get[‘module_id’] ) && ( $this->request->server[‘REQUEST_METHOD’] != ‘POST’ ) ) {
$module_info = $this->model_extension_module->getModule( $this->request->get[‘module_id’] );
}

І нарешті, ми завантажуємо такі елементи, як хедер, футер і лівий сайдбар. За це відповідає скорочення $this->load->view, яке завантажує файл подання recent_products.tpl і показує форму налаштувань.

У файлі контролера потрібно запам’ятати кілька важливих моментів. У файлі можна часто зустріти запис типу $this->load->ELEMENT, де ELEMENT може бути подання, модель або мову. Цей виклик завантажує відповідний вид, модель і мова компонентів.

Наступний і останній файл на сьогодні – шаблон виду admin/view/template/module/recent_products.tpl. Давайте створимо його!

Користувачі з хорошим зором вже помітили, що у файлі просто відображаються змінні з контролера. В іншому це простий XHTML код з формою налаштувань. Найголовніша фішка в тому, що код повністю адаптивний прямо з коробки. З створенням файлів для нашого back-end плагіна закінчили.

Включаємо плагін

Перейдіть в панель адміністратора OpenCart в Extensions > Modules. У списку має бути плагін Recent Products. Для установки модуля клікніть на +, як показано на скріншоті нижче.

Як створити власний плагін в OpenCart 2.1.x.x: частина 1

Після установки з’явиться іконка редагування. Клікніть по ній для відкриття форми налаштувань модуля.

Як створити власний плагін в OpenCart 2.1.x.x: частина 1

У формі конфігурації можна задати недавні продукти, які повинні відображатися в блоці на стороні front-end’а. Не забудьте встановити поле status в Enabled! Збережіть модуль, він повинен виглядати ось так.

Як створити власний плагін в OpenCart 2.1.x.x: частина 1

З’явилася нова рядок Recent Products > My Recent Block Plugin. Тобто модуль можна дублювати під різні сторінки! Майже закінчили! Ми створили повноцінний back-end плагін в OpenCart. У наступній частині ми розберемо front-end сторону питання, яка відповідає за показ блоку з товарами!

Висновок

Сьогодні ми почали створювати користувальницький плагін в OpenCart. У першій частині ми приділили увагу розробці на стороні back-end’а, а також створили робочий інтерфейс плагін з формою налаштувань.

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

У наступній частині ми завершимо розробку плагіна і створимо front-end складову, яка буде показувати список товарів. Свої питання та пропозиції пишіть в коментарях.

Як створити власний плагін в OpenCart 2.1.x.x: частина 1

Інтернет-магазин на OpenCart!

Створити інтернет-магазин на самій популярної CMS OpenCart з нуля!

Приступити до створення