msOptionsPrice2 и составной товар

Возникла необходимость при помощи msOptionsPrice2 реализовать составной товар. Оказалось, что компонент не умеет прибавлять к начальной цене товара несколько цен из модификаций одной опции.
Например, есть опция Наполнители, у нее около 20 значений. На фронте, при выборе каждого из значений, цена товара должна увеличиваться на N рублей. Проблема заключается в том, что имена тегам чекбоксов мы даем в виде массива:
<input type="checkbox" name="cb[]">Компонент, в свою очередь, с таким работать не умеет. Предлагаю решение в четыре простых шага!Решение проблемы
Предположим у нас есть опция Наполнители с ключом wok_fillers.
Шаг 1
При редактировании товара добавляем значения:
Шаг 2
Создаем модификацию для каждого значения, указывая:Тип = +
Цена = Сумма, которую нужно прибавить к начальной стоимости товара 
Шаг 3
На странице товара выводим список чекбоксов:{'!msOptionsPrice.modification' | snippet : [
'type' => 2,
'where' => [
'Option.key' => 'wok_fillers',
],
'sortby' => '{"msopModification.id": "ASC"}',
'limit' => 100,
'tpl' => '@INLINE
{foreach $options as $name => $value}
<div>
<label for="wok_fillers_{$idx}">
<input type="checkbox" name="options[{$name}][]" id="wok_fillers_{$idx}" value="{$value}"> {$value} <b style="color:red">(+{$modification.price} руб.)</b>
</label>
</div>
{/foreach}
',
]}Таким образом, мы выведем список модификаций для значений опции wok_fillers в виде чекбоксов, с прибавочной ценой рядом с названием значения.Шаг 4
Создаем плагин msopModificationPrice на событие msOnGetProductPrice, указывая приоритет 999. Высокий приоритет необходим для того, чтобы наш плагин отрабатывал после плагина msOptionsPrice.
switch ($modx->event->name) {
case "msOnGetProductPrice":
$returned = (array)$modx->getPlaceholder('_returned_price');
if (!isset($returned['price'])) {
return;
}
$id = $returned['id'];
$price = $returned['price'];
$options = !empty($returned['msoptionsprice_options'])
? $returned['msoptionsprice_options']
: (!empty($_REQUEST['options'])
? $_REQUEST['options']
: array());
$options = array_diff_key($options, array_flip(array('modifications', 'modification')));
foreach (array_keys($options) as $k) {
if (!empty($options[$k]) && is_array($options[$k])) {
foreach ($options[$k] as $v) {
$q = $modx->newQuery('msopModification')
->innerJoin('msopModificationOption', 'Option',
"Option.mid = msopModification.id AND Option.key = '{$k}' AND Option.value = '{$v}'")
->select(array('price'))
->where(array(
'msopModification.rid' => $id,
'msopModification.type' => 2,
'msopModification.active' => true,
))
;
if ($q->prepare() && $q->stmt->execute()) {
if ($price_add = $q->stmt->fetchColumn()) {
$price += $price_add;
}
}
}
}
}
$modx->event->returnedValues['price'] = $returned['price'] = $price;
$modx->setPlaceholder('_returned_price', $returned);
break;
} Итого
На странице товара, при выборе чекбоксов опции Наполнители к начальной цене будет прибавляться дополнительная стоимость каждой модификации этой опции.
Комментарии: 43
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Но, повторюсь, мог не уловить всей глубины задумки.
Однако не стал экспериментировать, т.к. клиент купил msOptionsPrice2 и msExtraFields. Второй — для решения задачи, описанной в данном посте (до сих пор не знаю, умеет ли он такое). После установки обоих, функция изменения стоимости у первого резко отвалилась. После изучения кода было ясно, что компоненты в одном проекте вместе не уживаются. Удалил второй (т.к. он не используется на проекте, в отличие от первого), еще немного поковырял первый и родилось вот такое решение.
Как ни крути, любые варианты решения задач полезны. Не исключаю. что в некоторых случаях такое решение будет рациональнее, чем приплетать msAddLinked.
наверно неверно сформулировал. Компонент просто не работает с опциями массивами…
для этого можно задействовать метод getModificationByOptions
ps. И да, для таких вопросов есть ТП в которой они успешно решаются…
Я бы отписал в ТП, только не я покупал компонент, а заказчик. Задачу было необходимо решить скорее, поэтому решил сам. Естественно,
когдаесли ты внедришь поддержку работы с массивами опций, то данное решение утратит актуальность и я его удалю. Только просьба сообщить об этом тут. :)Не собираюсь в ближайшее время это делать. Это повлияет на логику компонента…
Да и зачем удалять. Хороший пример как можно модифицировать стандартную логику расчета.
Павел, несколько вопросов:
1. …
Может, ..., а то не понимает скрипт, или у меня не работает…
2. У меня приходит не массив опций, а только одна, последняя опция. Не проходит проверку
3. Что за плейсхолдер _returned_price?
то естественно на сервер придет не массив, а только последнее значение…
, в плагине, на событие msopOnBeforeGetModification.
pdoTools 2.9.1-pl
msOptionsPrice2 2.3.33-beta
miniShop 2.4.11-pl
1. Чекбоксы указываются таки с параметром , тогда в массиве опций передается массив зачений.
2. У формы нужно указать (определить) скрытый , из-за этого, по сути, ничего и не выходило, проморгал.
с
на
, то есть, добавить к селектору name звездочку — *.
Возникла такая же, сразу добавляет цену к товару, а при отметке флажка добавляет еще раз…
В шаблоне карточки товара:
Чанк tpl.msOptionsFillers:
Но почему то не выводится добавочная цена {$modification.price}