Эмоциональное вступление
Вы уже почувствовали боль?...
Мне кажется именно так нужно начинать все статьи про расширение таблиц в MODX, а не "Удобно и очень просто". (Хотя этот вариант еще более-менее). Это п@#$ц как неудобно и вообще нихрена не просто. По крайней мере, когда тебе нужен результат не в точности такой, как описан в инструкции. Потому что много всяких нюансов, отчетов об ошибках нет никаких, и нет понимание логики системы. Кхм.. итак, приступим:)
В общем есть на данный момент 2 статьи, которые дают более-менее понятное описание — winrecovery.ru и docs.modx.pro. Одну из них я беру за основу.
Тут я постараюсь резюмировать хоть что-то, чтобы в следующий раз не рвать на себе волосы, пытаясь в течение часа "быстро, легко и удобно" добавить поле в minishop2.
(Василий, и прочие умные программисты — к вам претензий нет. Но вообще сама схема работы MODX в такие моменты просто убивает — когда простейшая задача становится самым сложным этапом в разработке сайта)
По сути
работы ведутся в контексте minishop2 2.4.11
Вероятно, вы уже знаете, что для того чтобы добавить новые поля, или изменить существующие, нужно создать плагин для MiniShop2. (Не имеет отношения к стандартным плагинам MODX). Этот плагин будет состоять из трех файлов, которые будут расположены:
core/components/minishop2/plugins/ms2extend1/index.php
core/components/minishop2/plugins/ms2extend1/msproductdata.troy.map.inc.php
assets/components/minishop2/plugins/ms2extend1/msproductdata.troy.js
ms2extend1 — это мое название плагина. Оно может быть произвольным
Сперва нужно вручную расширить таблицу MYSQL. То есть ручками через phpMyAdmin создаем нужную колонку в таблице [префикс]ms2_products
.
ms2extend1/index.php
Расположение: core/components/minishop2/plugins/ms2extend1/index.php
return array( 'xpdo_meta_map' => array( 'msProductData' => require_once dirname(__FILE__) .'/msproductdata.troy.map.inc.php' ) ,'manager' => array( 'msProductData' => MODX_ASSETS_URL . 'components/minishop2/plugins/ms2extend1/msproductdata.troy.js' ) );
ms2extend1/msproductdata.troy.map.inc.php
Расположение: core/components/minishop2/plugins/ms2extend1/msproductdata.troy.map.inc.php
Расширенную версию этого файла можно посмотреть по ссылке. Там представлены поля разных типов данных. Также можете ориентироваться на файл core/components/minishop2/model/minishop2/mysql/msproductdata.map.inc.php
— родной файл настроек minishop2. Он так же по ссылке.
fields
— значение по-умолчанию для поляfieldMeta
— Meta-описание поля. Тут надо все четко заполнить:)indexes
— Индексы. На сколько я понимаю - если вы создали индекс в таблице MySQL, то тут его тоже следует указать, а иначе можно не указывать.
return array( 'fields' => array( 'currency' => NULL ) ,'fieldMeta' => array( 'currency' => array( 'dbtype' => 'varchar' ,'precision' => '5' ,'phptype' => 'string' ,'null' => true ,'default' => NULL ) ) ,'indexes' => array( 'currency' => array ( 'alias' => 'currency' ,'primary' => false ,'unique' => false ,'type' => 'BTREE' ,'columns' => array ( 'action' => array ( 'length' => '' ,'collation' => 'A' ,'null' => false ) ) ) ) );
ms2extend1/msproductdata.troy.js
Расположение: assets/components/minishop2/plugins/ms2extend1/msproductdata.troy.js
Этот файл отвечает за представление полей в админке, и соответственно тут вы можете указать какой будет тип инпута. Этих типов хренова туча, и вот в этом файле тоже есть примеры нескольких вариантов. Стандартные поля MiniShop2 можно посмотреть тут - это файлик минишопа (assets/components/minishop2/js/mgr/product/product.common.js
).
Прочитайте еще комментарии в самом файле, там написано про заголовок поля:
miniShop2.plugin.pluginname = { //pluginname менять не надо. getFields: function(config) { return { // То, что тут написано [[+currency]] - это просто выводится как есть, то есть это не плейсхолдер. // А вот ms2_product_currency_help - это уже ключ словаря, и его нужно создать в разделе "Управление словарями -> minishop2 -> ru" или можно просто текстом прописать и не париться currency: {xtype: 'minishop2-combo-autocomplete', description: '[[+currency]]
'+_('ms2_product_currency_help')} } } ,getColumns: function() { return { currency: {width:50, sortable:false, editor: {xtype:'minishop2-combo-autocomplete', name: 'currency'}} } } };
Отображение заголовков у полей
Для того чтобы появились подписи у полей нужно добавить записи в разделе "Управление словарями -> minishop2 -> ru". Алгоритм формирования ключа такой — ms2_product_FIELDNAME
"And.. One more thing" (Почему не работает)
Нужно еще явно указать в настройках, что вы хотите отображать это новое поле.
Переходим в Настройки
-> minisop2
-> Товар
-> Дополнительные поля товара (ms2_product_extra_fields)
, и дописываем туда название вашего поля.
Если на данном этапе не отображается заголовок, прочитайте комментарии для файла JS настроек. Там про это написано.
И еще, у меня почему-то не отображались изменения, пока я не нажал Ctrl+F5
(В хроме — перезагрузка стрницы с очисткой кэша).
Форматирование нового поля цены при выводе
Для таких полей как цена, потребуется еще одна правка. В данном случае я решил ее костылем, хотя стоило бы реализовать все правильно, с расширением объекта.
В общем, открываем файлик core/components/minishop2/model/minishop2/msproduct.class.php
, находим там public function process()
, и дальше все станет понятно.
P.S.
Если я, так же, как и другие авторы, упустил какой-то важный нюанс, или посчитал что-то очевидным и не разъяснил, и от этого у вас ничего не работает, то излейте свою ненависть в комментариях. Спасибо. И простите меня..
Вкладку свою сделал так.
Ext.override(miniShop2.panel.Product, {
ms__Originals: {
getFields: miniShop2.panel.Product.prototype.getFields,
},
getFields: function (config) {
var fields = this.ms__Originals.getFields.call(this, config);
for (var i in fields) {
if (!fields.hasOwnProperty(i)) {
continue;
}
var item = fields[i];
if (item.id == «modx-resource-tabs») {
for (var i__2 in item.items) {
if (!item.items.hasOwnProperty(i__2)) {
continue;
}
var tab = item.items[i__2];
if (tab.id == «minishop2-product-tab» && tab.items[0]) {
tab.items[0].items.push({
title: 'Название вкладки',
autoHeight: true,
hideMode: 'offsets',
cls: 'x-panel-body main-wrapper x-panel-body-noheader x-panel-body-noborder',
layout: 'form',
anchor: '100%',
items: [{
html: 'Текст',
bodyCssClass:'x-panel',
border: false
},{
layout: 'column',
items:[{
columnWidth: .33,
layout: 'form',
items: [{
// здесь список созданных полей 1, 4, 7
}]
},{
columnWidth: .33,
layout: 'form',
items: [{
// здесь список созданных полей 2, 5, 8
}]
},{
columnWidth: .33,
layout: 'form',
items: [{
// здесь список созданных полей 3, 6, 9
}]
}]
}]
});
}
}
}
}
return fields;
},
});
Вот пара заметок, в которых я описывал что-то подобное:
Изменить цену на товар, если в корзине лежит товар из особой категории minishop2 — webstool.ru/izmenit-czenu-na-tovar-esli-v-korzine-lezhit-tovar-iz-osoboj-kategorii-minishop2.html
Изменить цену на товар в зависимости от количества при добавлении в корзину minishop2 — webstool.ru/izmenit-czenu-na-tovar-minishop2.html
А может знаете где minishop берет название столбца БД с ценой? Чтобы добавив новый столбец в базу данных указать его название. Тогда, по идее, будет меньше заморочек с обработкой цен в корзине
По ссылкам, которые я дал вы можете увидеть как я обращаюсь к цене:
Соответственно, после создания ваших собственных полей с ценами у вас будет что-то то типа описанного вот тут webstool.ru/izmenit-czenu-na-tovar-minishop2.html
… Хм, вопрос был немного не о том, наверно… Ну minishop просто оперирует полем price, а это поле, соответственно находится в [префикс]ms2_products. Не думаю, что есть какая-то настройка, позволяющая передать функции этого поля какому-то другому полю.
А согласно инструкции, описанной на этой странице создавать свои поля вы можете расширив эту таблицу. Но просто очень важно, чтобы вы прошли через все необходимые круги ада, для того чтобы мочь воспользоваться конструкцией $product->get('priceUSD');