Автор этой записи несколько лет назад сам искал информацию по этой теме и скажу, что материала достаточно не много. OpenCart только начал обрастать атрибутами серьезного проекта. В моем понимании это автоматизированные тесты и документация. Если у вас со знанием английского есть небольшие сложности, можно поискать и найти документацию для разработчиков на русском языке, за что ребятам большое спасибо. Кстати, проект открыт и вы тоже можете присоединиться к описанию классов и файлов, если есть свободное время и желание.
Сегодня мы напишем простой модуль для OpenCart 2.3 – самой свежей на момент написания статьи версии этого движка интернет магазина.
В качестве примера мы создадим модуль Яндекс.Метрики с админ частью по аналогии с предустановленным модулем Google Analytics. Несмотря на свою продвинутую мультиязычность, комьюнити OpenCart не особо заморачивается с поддержкой различных систем сбора аналитики (что-то кроме Google Analytics), хотя их существует множество – Яндекс.Метрика,Piwik, Adobe Marketing Cloud, Kissmetrics, Open Web Analytics и многое другое. Лично я считаю это недочетом. Давайте исправлять.
Итак, сейчас в разделе Модули->Расширения->Аналитика вы увидите следующую картину:
Мы будем добавлять новый модуль Яндекс.Метрика, взяв за основу существующий – Google Analytics. Т.е. после наших действий этот экран должен выглядеть так:
Не удивляйтесь почему модули оформлены Разделами. Дело в том, что OpenCart отлично поддерживает мультимагазин, т.е. возможность размещения на одном сервере и бекенде нескольких магазино с различными товарами, оформление и конечно же модулями (расширениями). Соответственно для каждого подмагазина (возможно) понадобится свой код счетчика.
Начинаем
Наш будущий модуль имеет сразу две части – публичную в качестве добавления кода счетчика Яндекс.Метрики на страницы и административную, где модуль можно включать-выключать, а так же вносить изменения в код счетчика. Начнем с административной части.
Административная часть модуля
Любой модуль OpenCart начинается с контроллера, т.к. движок написан на паттерне MVC. Поэтому в папке admin/controller/extension/analytics
создайте новый файл yandex_metrica.php
Должно получиться так:
Теперь, начнем этот файл наполнять логикой, беря за основу находящийся уже в этой папке контроллер google_analytics.php
.
Я всегда советую начинать писать модули с копирования существующих и переделывания их под себя, т.к. документация по OpenCart, особенно в части написания модулей оставляет желать лучшего.
Объявим новый класс ControllerExtensionAnalyticsYandexMetrica
как дочерний глобального класса Controller
, а также используя модификатор области видимости private
объявим переменную в виде массива, в который будут записываться ошибки. Эта строка обязательная для корректной отладки своего модуля, а так же логирования ошибок PHP в служебный файл лога.
<?php class ControllerExtensionAnalyticsYandexMetrica extends Controller { private $error = array();
Далее создадим функцию index(). Эта функция исполняется при попытке прямого обращения к нашему модулю через GET запрос index.php?route=extension/analytics/yandex_metrica
public function index() {
Первым делом создадим файл локализации yandex_metrica.php
для нашего модуля в папке /admin/language/ru-ru/extension/analytics
. Все конечно понимают, что в данном случае мы создаем русскую локализацию модуля. Если вы хотите создать для английской версии, то путь немного отличается /admin/language/
en-gb
/extension/analytics
, эта локализация кстати базовая для OpenCart и он будет брать ее в случае отсутствия у него локализации для выбранного в настройках магазина языка.
Содержание этого файла:
<?php $_['heading_title'] = 'Яндекс.Метрика'; // Text $_['text_extension'] = 'Расширения'; $_['text_success'] = 'Настройки успешно изменены!'; $_['text_signup'] = 'Войдите в аккаунт <a href="https://metrika.yandex.ru/list" target="_blank"><u>Яндекс.Метрику</u></a> и после создания профиля сайта, скопируйте, а затем вставьте код в данное поле.'; $_['text_default'] = 'По умолчанию'; $_['text_edit'] = 'Настройки модуля'; // Entry $_['entry_code'] = 'Код Яндекс.Метрики'; $_['entry_status'] = 'Статус'; // Error $_['error_permission'] = 'У Вас нет прав для управления данным модулем!'; $_['error_code'] = 'Код необходим!';
Теперь мы можем вернуться к коду контроллеру и подключить этот файл локализации в наш контроллер /admin/controller/extension/analytics/yandex_metrica.php
. Так же присвоим некоторым переменным значения.
// Подключим файл локализации $this->load->language('extension/analytics/yandex_metrica'); //Зададим заголовок страницы, мета-тег title из файла локализации $this->document->setTitle($this->language->get('heading_title')); // Зададим название модуля в списке модулей $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['text_signup'] = $this->language->get('text_signup'); // Текст метки поля "Код" $data['entry_code'] = $this->language->get('entry_code'); // Текст метки переключателя статуса модуля $data['entry_status'] = $this->language->get('entry_status'); // Текст кнопки "Сохранить" $data['button_save'] = $this->language->get('button_save'); // Текст кнопки "Отменить" $data['button_cancel'] = $this->language->get('button_cancel');
Теперь добавим немного логики. Подключим Модель для работы с глобальной таблицей настроек OpenCart – setting, зададим логику обработки предупреждений и ошибок, а так же напишем что будет происходить при нажатии кнопки “Сохранить”.
$this->load->model('setting/setting'); if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) { $this->model_setting_setting->editSetting('yandex_metrica', $this->request->post, $this->request->get['store_id']); $this->session->data['success'] = $this->language->get('text_success'); $this->response->redirect($this->url->link('extension/extension', 'token=' . $this->session->data['token'] . '&type=analytics', true)); } if (isset($this->error['warning'])) { $data['error_warning'] = $this->error['warning']; } else { $data['error_warning'] = ''; } if (isset($this->error['code'])) { $data['error_code'] = $this->error['code']; } else { $data['error_code'] = ''; }
Логика написанного достаточно проста. Сначала мы подключаем модель для работы с таблицей глобальных настроек OpenCart $this->load->model('setting/setting');
, дальше с помощью конструкции if
мы задали условие, что если есть запрос методом POST
и он прошел валидацию, то мы сохраняем полученные данные в БД с помощью функции модели editSetting
. Обратите внимание, что функция получили в качестве параметров кроме прочего и значение store_id
. Как я говорил выше, OpenCart поддерживает мультимагазин и параметр store_id
позволяет разделять настройки для разных подмагазинов.
Дальше, если валидация не прошла (т.е. перемеменные $this->error['code']
и $this->error['warning']
не пустые) данные не будут сохранены, а текст ошибки выведется на странице модулей.
Давайте создадим хлебные крошки, которые потом выведем в Представлении, у нас они 3-го уровня вложенности: Главная страница админки -> Модули -> Яндекс.Метрика
$data['breadcrumbs'] = array(); $data['breadcrumbs'][] = array( 'text' => $this->language->get('text_home'), 'href' => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], true) ); $data['breadcrumbs'][] = array( 'text' => $this->language->get('text_extension'), 'href' => $this->url->link('extension/extension', 'token=' . $this->session->data['token'] . '&type=analytics', true) ); $data['breadcrumbs'][] = array( 'text' => $this->language->get('heading_title'), 'href' => $this->url->link('extension/analytics/yandex_metrica', 'token=' . $this->session->data['token'] . '&store_id=' . $this->request->get['store_id'], true) );
Обратите внимание, что с точки зрения разработчиков OpenCart хлебные крошки нужно хранить в многомерном массиве, который потом будет выводиться в цикле foreaсh
. Ничего против такого подхода не имею.
Обращаю внимание начинающих разработчиков OpenCart на булевое значение переменной true
в значении переменной массива $data['breadcrumbs']['href']
. Тот, кто уже знаком с более ранними версиями OpenCart безусловно знает, что раньше там было значние SSL
, например, как бы этот код выглядел в OpenCart 1.5.6.4:
$this->data['breadcrumbs'][] = array( 'text' => $this->language->get('heading_title'), 'href' => $this->url->link('extension/payment', 'token=' . $this->session->data['token'], 'SSL'), 'separator' => ' :: ' );
Значние константы SSL, а теперь уже булевой переменной true определяет префикс http(s):// в URL Представления. Если у вас в настройках файла config.php указаны значения констант для путей с https://
< ?php // HTTP define('HTTP_SERVER', 'http://yourdomain.tdl/admin/'); define('HTTP_CATALOG', 'http://yourdomain.tdl/'); // HTTPS define('HTTPS_SERVER', 'https://yourdomain.tdl/admin/'); define('HTTPS_CATALOG', 'https://yourdomain.tdl/');
Так же для полноценной работы HTTPS необходимо настроить соответствующий параметр в административной части:
Однозначно возникает вопрос, зачем так заумно решать эту задачу с HTTPS? Например, если у нас включен HTTPS для магазина, а ссылка, которую вы хотите поставить должна вести на обычный http://… Сценариев, где это может понадобиться я пока не встречал, но смею предположить, что речь идет о внешних ссылках, т.к. HTTPS зачастую включают для всего сайта целиком – административной и пользовательской части. Автор статьи настоятельно рекомендует использовать именно такой способ формирования ссылок: из Контроллера в Представление через переменную $this->url->link
, т.к. в этом случае они корректно работают с ЧПУ OpenCart.
Продолжим писать код в наш контроллер. Добавим код, который будет отвечать за код ссылки кнопок Редактирования и Отмены в списке подмагазинов и определим получения токена. Токен нужен для сессии, т.к. административная часть защищена паролем.
$data['action'] = $this->url->link('extension/analytics/yandex_metrica', 'token=' . $this->session->data['token'] . '&store_id=' . $this->request->get['store_id'], true); $data['cancel'] = $this->url->link('extension/extension', 'token=' . $this->session->data['token'] . '&type=analytics', true); $data['token'] = $this->session->data['token'];
Напишем два условия на значение полей – поля для самого кода Яндекс.Метрики и переключателя статуса Включено-Выключено.
if (isset($this->request->post['yandex_metrica_code'])) { $data['yandex_metrica_code'] = $this->request->post['yandex_metrica_code']; } else { $data['yandex_metrica_code'] = $this->model_setting_setting->getSettingValue('yandex_metrica_code', $this->request->get['store_id']); } if (isset($this->request->post['yandex_metrica_status'])) { $data['yandex_metrica_status'] = $this->request->post['yandex_metrica_status']; } else { $data['yandex_metrica_status'] = $this->model_setting_setting->getSettingValue('yandex_metrica_status', $this->request->get['store_id']); }
Если есть POST запрос, то содержание переменной кода берется из значения поля формы в Представлении и передается в Контроллер, в противном случае Контроллер передает в Представление значение, которое записано в БД и получено от Модели. Аналогично происходит и с полем Статус.
Осталось дописано всего несколько строк.
$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('extension/analytics/yandex_metrica', $data)); }
Т.к. блок шапки, левой колонки и футера обрабатывается в отдельных Контроллерах, их нужно подключать отдельно, чтобы вывести в Представлении.
Последняя команда непосредственно отвечает за передачу всех данных из Контроллера в Представление.
Осталось написать еще одну функцию validate() в нашем классе модуля и можно считать, что с контроллером мы расправились.
protected function validate() { if (!$this->user->hasPermission('modify', 'extension/analytics/yandex_metrica')) { $this->error['warning'] = $this->language->get('error_permission'); } if (!$this->request->post['yandex_metrica_code']) { $this->error['code'] = $this->language->get('error_code'); } return !$this->error; } }
Все конечно же понимают, что в данной функции мы проверям наличие прав на редактирование модуля, а также не попытался ли пользователь передать в Контроллер из Представления пустое поле Код. Теоретически у нас может и отсутствовать код, но для этого есть поле Статус, которым можно отключить отображение кода счетчика в клиентской части, тем самым оптимизировав вывод интерпретатором PHP кода.
Мы сэкономили на кодировке Модели для этого модуля, но т.к. Представление будет передавать нам Поля HTML с другими именами, его все таки придется создать, чем мы и займемся в следующей части этой статьи.
В третьей версии тот же путь? Или что-то новое?
Twig, а так все очень похоже.
Добро время суток!
Искал готовый модуль, обмена но нашел Вашу замечательную статью.
Сделал все шаг за шагом, установил на хостинг.
Первый косяк у меня получился вот так:
http://dl4.joxi.net/drive/2021/02/18/0007/4017/520113/13/2b0e27f8a0.jpg
Как это можно исправить ?
Заранее благодарю!
Какая версия OpenCart?
В старых версиях там ошибка в верстке