Только для читателей Lifeexample возможно открыть интернет-магазин на Moguta.CMS со скидкой в 15%
Moguta.CMS – разработка плагина скидок
Здравствуйте, уважаемые читатели блога LifeExample, в этой статье я научу вас самостоятельно делать расширения Moguta.CMS, на примере создания плагина скидок.
Изначально в основу проекта Могута, была заложена идея создания легкой админки. Панель администрирования не должна была стать похожей на сотни однотипных, навороченных разным функционалом продуктов. И это получилось! Периодически мне на email приходят положительные отзывы о продукте, именно с точки зрения понятности админки и легкости управления магазином.
Посмотрите следующий ролик и оцените панель администрирования Moguta.CMS. Выскажите свое мнение в комментариях к данной статье.
В ходе разработки CMS большое внимание уделялось системе плагинов, позволяющих нарастить функционал для каждого магазина индивидуально.
Согласитесь, ведь не всем может понадобиться вести ленту новостей на своем сайте или иметь возможность общаться с пользователями через их личные кабинеты, так зачем это включать в базовый набор функций системы?
Предлагаю в данной статье вместе разработать, полезный многим, плагин скидок для товаров интернет-магазина.
Сначала я подумал о том, что надо сделать такой плагин, который бы мог оперировать набором скидок, например, устанавливать скидки на разные категории товаров, или на отдельные товары, а также учитывать сроки действия скидок. Но в рамках одной статьи будет сложно описать все нюансы реализации, поэтому было принято решение, пока, сделать лишь заготовку показав основные возможности системы плагинов, а в одной из следующих статей продолжить разработку и нарастить функционал до управления скидками.
Задачи плагина скидок:
- Добавить в панель инструментов интерфейс для редактирования скидки;
- При выводе стоимости товаров в публичной части показывать рядом с новой ценой зачеркнутую старую цену;
Подготовка
На самом деле, на официальном сайте могуты есть статья "Создание плагина для Moguta.CMS", в которой довольно четко описаны основные требования к плагинам. Рекомендую изучить ее прежде чем двигаться дальше.
Прочитали? Хорошо, тогда вы должны были усвоить несколько основных моментов:
- Все плагины располагаются в папке mg-plugins;
- Каждый плагин хранится в именованной папке и обязательно содержит файл index.php, в котором первым комментарием задана служебная информация;
- Названия папок плагинов должны быть в нижнем регистре;
- Плагин необходимо активировать в разделе "Плагины" панели администрирования;
- Не все плагины имеют свою страницу настроек;
- После активации некоторых плагинов появляется возможность работать с его шорткодами;
Если вы ранее создавали плагины для wordpress или читали статью моего блога "Пишем плагин WordPress", то вы заметите много сходств с процессом разработки плагина для Moguta.CMS.
Начало
Перейдем к практике. Создадим в папке mg-plugins/ новый каталог: discount-panel, в него добавим следующий файл index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | <?php /* Plugin Name: Панель скидок Description: Устанавливает скидку/наценку на определенную группу товаров. Author: Avdeev Mark Version: 1.0 */ new DiscountPanel; class DiscountPanel{ private static $arrayProducts = array(); // массив продуктов с новыми ценами, выводимый на генерируемую странице. public function __construct(){ mgActivateThisPlugin(__FILE__, array(__CLASS__, 'createDateBase')); mgAddAction(__FILE__, array(__CLASS__, 'pageSettingsPlugin')); if(!URL::isSection('mg-admin')){ mgAddShortcode('old-price', array(__CLASS__, 'oldPrice')); mgAddAction('models_catalog_getlist' , array(__CLASS__, 'discountToCatalog'), 1); mgAddAction('models_product_getproduct' , array(__CLASS__, 'discountToProduct'), 1); mgAddAction('models_catalog_getlistproductbykeyword' , array(__CLASS__, 'discountToSearch'), 1); mgAddAction('smalcart_getcartdata' , array(__CLASS__, 'discountToSmalCart'), 1); } } /** * Создает таблицу для скидок в БД при активации плагина */ static function createDateBase(){ DB::query(" CREATE TABLE IF NOT EXISTS `".PREFIX."discount` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Порядковый номер скидки', `cat_id` int(11) NOT NULL COMMENT 'Категория на которую растпространяется скидка', `prod_ids` text CHARACTER SET utf8 NOT NULL COMMENT 'Номера товаров попадающих под скидку, если пусто - значит все.', `persent` int(11) NOT NULL DEFAULT '0' COMMENT 'Процент скидки', `date_start` date NOT NULL COMMENT 'Дата начала скидки', `date_end` date NOT NULL COMMENT 'Дата завершения скидки', `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Действие скидки', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;"); DB::query(" INSERT INTO `".PREFIX."discount` ( `id` , `cat_id` , `prod_ids` , `persent` , `date_start` , `date_end` , `enabled` ) VALUES ( 1 , '0', '', '10', now(), now(), '1' ); " ); } /** * Выводит страницу настроек плагина в админке */ static function pageSettingsPlugin(){ if(isset($_POST['discount']) && is_numeric($_POST['discount'])){ $discount = $_POST['discount']; DB::query(" UPDATE `".PREFIX."discount` SET `persent` = ".DB::quote($discount)." WHERE id=1 "); echo "<br/> Установлена новая скидка на все товары: ".$discount."%"; } else{ $discount = self::getDiscount(); }; echo ' <div class="discount-block" style="margin: 50px;"> <form methot="post" action=""> Скидка на все товары: <input type="text" name="discount" value="'.$discount.'"/> %. <br/> <input type="hidden" name="pluginTitle" value="'.$_POST['pluginTitle'].'"/> <input type="submit" value="Применить"/> </form> </div>'; } /** * Получает текущую скидку на все товары */ static function getDiscount(){ $discount = 0; $res = DB::query(" SELECT `persent` FROM `".PREFIX."discount` WHERE `id`= 1"); if($row = DB::fetchAssoc($res)){ $discount = $row['persent']; } return $discount; } /** * Применяет скидку к ценам выводимым для продуктов в каталоге */ static function discountToCatalog($arg){ foreach ($arg['result']['catalogItems'] as &$item) { // сохраняем старую цену продукта для последующего вывода шорткодом self::$arrayProducts[$item['id']]['oldPrice'] = $item['price']; $item['price'] = self::applyDiscount($item['price']); // сохраняем новую цену для продукта для последующего вывода шорткодом self::$arrayProducts[$item['id']]['newPrice'] = $item['price']; } return $arg['result']; } /** * Применяет скидку к ценам для продуктов в карточке товара */ static function discountToProduct($arg){ self::$arrayProducts[$arg['result']['id']]['oldPrice'] = $arg['result']['price']; $arg['result']['price']=self::applyDiscount($arg['result']['price']); self::$arrayProducts[$item['id']]['oldPrice'] = $arg['result']['price']; return $arg['result']; } /** * Применяет скидку к ценам для продуктов в карточке товара */ static function discountToSearch($arg){ foreach ($arg['result']['catalogItems'] as &$item) { self::$arrayProducts[$item['id']]['oldPrice'] = $item['price']; $item['price'] = self::applyDiscount($item['price']); self::$arrayProducts[$item['id']]['newPrice'] = $item['price']; } return $arg['result']; } /** * Применяет скидку к ценам для продуктов в маленькой корзине */ static function discountToSmalCart($arg){ if(isset($arg['result']['dataCart'])){ $arg['result']['cart_price'] = 0; foreach ($arg['result']['dataCart'] as &$item) { $item['price'] = self::applyDiscount($item['price']); $item['priceInCart'] = $item['price']." ".MG::getSetting('currency'); $arg['result']['cart_price'] += $item['price'] * $item['countInCart']; } } $arg['result']['cart_price_wc'] = $arg['result']['cart_price']." ".MG::getSetting('currency'); return $arg['result']; } /** * Применяет скидку к ценам продуктов */ static function applyDiscount($price){ $price = $price - self::getDiscount()*$price/100; return $price; } /** * Обработчик шотркода вида [old-price id="7"]1060[/old-price]. * Выводит новую цену товара, зачеркивая старую. */ static function oldPrice($arg){ $id = $arg['id']; $newPrice = $arg['content']; $oldPrice = isset(self::$arrayProducts[$id]['oldPrice'])?self::$arrayProducts[$id]['oldPrice']:'undefined'; return "<span style='text-decoration:line-through; color: orange;'>".$oldPrice.' '.MG::getSetting('currency')."</span> <br/> <span>".$newPrice."</span>"; } } |
Всё, плагин готов, его можно активировать и использовать! После активации у вас появится отдельная страница настроек скидок.

Пишите свои комментарии в конце статьи, подписывайтесь на продолжение, в котором мы усовершенствуем плагин скидок, всего доброго дорогие друзья!
Шучу! 🙂
Конечно же, я объясню по порядку, что происходит в этом коде, и как оно работает.
Вникаем в код
Во-первых, мы создали отдельный класс DiscountPanel отвечающий за логику работы скидок, и самым интересным кодом в этом классе является код в теле конструктора:
1 2 3 4 5 6 7 8 9 10 11 12 | public function __construct(){ mgActivateThisPlugin(__FILE__, array(__CLASS__, 'createDateBase')); mgAddAction(__FILE__, array(__CLASS__, 'pageSettingsPlugin')); if(!URL::isSection('mg-admin')){ mgAddShortcode('old-price', array(__CLASS__, 'oldPrice')); mgAddAction('models_catalog_getlist' , array(__CLASS__, 'discountToCatalog'), 1); mgAddAction('models_product_getproduct' , array(__CLASS__, 'discountToProduct'), 1); mgAddAction('models_catalog_getlistproductbykeyword' , array(__CLASS__, 'discountToSearch'), 1); mgAddAction('smalcart_getcartdata' , array(__CLASS__, 'discountToSmalCart'), 1); } } |
Для новичков в программировании он может быть несколько пугающим, но на самом деле является шаблонным для плагинов Moguta.CMS и поэтому достаточно один раз вникнуть в его суть.
В коде происходит привязка методов класса к разного рода событиям системы.
Например, строка:
1 | mgAddAction('models_catalog_getlist' , array(__CLASS__, 'discountToCatalog'), 1); |
означает, что когда системой будет инициализировано событие ‘models_catalog_getlist’, то должен выполниться статический метод данного класса ‘discountToCatalog’, внеся свои коррективы в работу метода getList() в классе Models_Catalog.
Как видите, в коде используется несколько функций системы для задания привязок:
- mgActivateThisPlugin — определяет метод класса, который будет происходить всякий раз при активации плагина.
- mgAddShortcode – определяет обработчик для шорткода [old-price]
- mgAddAction – позволяет привязать свой метод к определенному событию системы, подробнее о событиях читайте в статье "Система работы плагинов в Moguta.CMS"
В коде мы видим особое применение функции mgAddAction, в которую мы передаем директиву __FILE__:
1 | mgAddAction(__FILE__, array(__CLASS__, 'pageSettingsPlugin')); |
Такое применение привязывает метод данного класса ‘pageSettingsPlugin’, который будет отвечать за генерацию контента на странице настроек плагина в панели администрирования.
Еще один важный момент. Поскольку данный плагин немного специфичен и его методы действуют на все выводы цен, не только в публичной части, но и в админке, то нужно задать условие позволяющее применять скидку только для публичной части:
1 | if(!URL::isSection('mg-admin')){ … } |
Методом URL::isSection мы вычислим, что работа ведется в административном разделе и предотвратим обработку вывода цен для продукта данным плагином.
На этом все необходимые действия для дальнейшей работы плагина, осуществлены и мы можем смело писать код привязанных нами методов.
- createDateBase() — создает таблицу для скидок в БД при активации плагина;
- pageSettingsPlugin() — выводит страницу настроек плагина в админке;
- getDiscount() — получает текущую скидку на все товары;
- discountToCatalog($arg) — применяет скидку к ценам выводимым для продуктов в каталоге;
- discountToProduct($arg) — применяет скидку к ценам для продуктов в карточке товара;
- discountToSearch($arg) — применяет скидку к ценам для продуктов в результате поискаа;
- discountToSmalCart($arg) — применяет скидку к ценам для продуктов в маленькой корзине;
- applyDiscount($price) — применяет скидку к ценам продуктов;
- oldPrice($arg) — обработчик шотркода вида [old-price id=»7″]1060[/old-price]. Выводит новую цену товара, зачеркивая старую.
Немного о событиях
Заострим внимание на методах discountToCatalog($arg), discountToProduct($arg), discountToSearch($arg), discountToSmalCart($arg).
Всех их объединяет наверняка непонятный вам массив $arg.
На примере метода discountToCatalog(), параметр $arg – это массив аргументов передающийся при генерации движком события ‘models_catalog_getlist’, к которому привязан метод плагина:
1 | mgAddAction('models_catalog_getlist' , array(__CLASS__, 'discountToCatalog'), 1); |
В данном случае в $arg[‘args’] попадут все переменные, которые были переданы в getList() в классе Models_Catalog, а в $arg[‘result’] результат работы метода getList().
Это значит, что если мы в методе discountToCatalog() просто вернем $arg[‘result’]:
1 2 3 | static function discountToCatalog($arg){ return $arg['result']; } |
то ничего не изменится. А если в тело функции вставить какой-то код, влияющий на массив $arg[‘result’]:
1 2 3 4 5 6 7 8 9 10 11 12 | static function discountToCatalog($arg){ foreach ($arg['result']['catalogItems'] as &$item) { // сохраняем старую цену продукта для последующего вывода шорткодом self::$arrayProducts[$item['id']]['oldPrice'] = $item['price']; $item['price'] = self::applyDiscount($item['price']); // сохраняем новую цену для продукта для последующего вывода шорткодом self::$arrayProducts[$item['id']]['newPrice'] = $item['price']; } return $arg['result']; } |
То результат будет на лицо:

Четыре, практически, одинаковых метода нужны потому, что в разных местах сайта товары выводятся разными методами и поэтому генерируют разные события. Для каталога будет генерироваться событие ‘models_catalog_getlist’, для страницы с подробным описанием товара — ‘models_product_getproduct’, для результатов поиска — ‘models_catalog_getlistproductbykeyword’, для маленькой корзины — ‘smalcart_getcartdata’.
Шорткоды
Не менее интересным, в данном классе является метод oldPrice($arg). В отличии от рассмотренных ранее методов, этот привязан функцией:
1 | mgAddShortcode('old-price', array(__CLASS__, 'oldPrice')); |
которая определила шорткод [old-price], это значит, что всякий раз кода будет использоваться шорткод такого вида [old-price id=»7″]1060[/old-price], то в метод oldPrice($arg) будет попадать arg[‘id’]=7 и arg[‘content’]= 1060. Можно передавать любые аргументы на подобии ‘id’.
К примеру, если указать в шорткоде [old-price id=»7″ paramet =»exclusive»]содержание[/old-price], то $arg будет содержаться элементы:
1 | array('id'=>7, 'paramet '=> 'exclusive', 'content'=>'содержание' ); |
Заключение
В данной статье мы рассмотрели код, несложного плагина скидок для Moguta.CMS. Я надеюсь, мои пояснения помогли вам усвоить основные принципы создания плагина. Напишите в комментариях, хотели бы вы увидеть продолжение материала и еще больше разобраться с разработкой плагинов для Moguta.CMS.
Читайте также похожие статьи:
Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.
Комментарии
Не работает. Выдает следующее:
Ошибка в SQL запросе: SELECT `persent` FROM `mg_discount` WHERE `id`= 1
Table ‘u511598273_tin.mg_discount’ doesn’t exist
/home/u511598273/public_html/mg-plugins/discount-panel/index.php (line 92)
/home/u511598273/public_html/mg-plugins/discount-panel/index.php (line 73)
(line )
/home/u511598273/public_html/mg-core/lib/eventhook.php (line 68)
/home/u511598273/public_html/mg-core/lib/pm.php (line 207)
/home/u511598273/public_html/mg-core/lib/mg.php (line 201)
/home/u511598273/public_html/mg-admin/section/views/plugintemplate.php (line 10)
/home/u511598273/public_html/mg-core/lib/mg.php (line 712)
/home/u511598273/public_html/mg-core/lib/mg.php (line 513)
/home/u511598273/public_html/mg-core/mg-start.php (line 49)
/home/u511598273/public_html/index.php (line 86)
Спасибо, поправил в статье и перезалил архив.
Плагин очень полезный и перспективный, ждем следующую статью по управлению скидками. Удачи Вам.
Выдает ошибку
Fatal error: Call to undefined method MG::getSetting() in Z:\home\localhost\www\mg-plugins\discount-panel\index.php on line 154
Видимо вы используете версию 3.0.2. Скачайте и установите обновленную CMS 3.0.3. Или замените в данном плагине все MG::getSetting() на MG::getOption().
Для того чтобы вывести зачеркнутую цену нужно:
вставить шорткоды
[old-price id=»< ?php echo $item["id"] ?>«]< ?php echo $item["price"] ?>[/old-price]
этот в catalog.php
[old-price id=»< ?php echo $data["id"] ?>«]< ?php echo $data["price"] ?>[/old-price]
этот в product.php
Этот плагин применяется ко всем товарам, а можно как то его модифицировать, чтобы он применялся к конкретному товару? Или только к одной категории?
Это есть в планах. В следующей части статьи я опишу как это реализовать.
возможно ли написание плагина, с включением которого будет появляться поле при редактировании товара, например чтобы старая цена была полем при редактировании товара?
Возможно, пишите на мейл, обсудим стоимость.
Здравствуйте Mark!
Подскажите пожалуйста — как вывести на продуктах в Каталоге(обычную) зачеркнутую цену… имеющуюся в стандартном функционале шаблона. И ещё сразу как вывести под продуктами в Каталоге сразу и выбор размеров.
Что бы накидывать в корзину сразу из каталога. Спасибо.
В новой версии системы, зачеркивание старой цены реализована базовым функционалом.
Скидка НЕ применяется к товара с пометками New и рекомендуемые, которые выводятся отдельным блоком.
Здравствуйте подскажите пожалуйста поставил плагин он везде работает кроме описания товара discountToProduct… Видимо движок новый и getProduct уже переписан. Подскажите пожалуйста как изменить discountToProduct чтоб он заработал. Большое спасибо