Динамическое обновление основной корзины

У MS2 есть хорошая вещь как возможность расширения класса msCartHandler. Все обновленные данные берутся $miniShop2->cart->status() и отсюда следует что нужно в этот массив данных дописать нужные нам данные, а именно список товаров которые попадут в [[+goods]]

И так начнем «колдовать»!Для начала создаем в папке core/components/minishop2/custom/cart файл msсartзroductрandler.class.php с следующим содержимым:

<?php
class msCartProductHandler extends msCartHandler {
 // сюда будут добавляться модифицированные функции
}
Далее я залез в файл mscarthandler.class.php чтобы скопировать код функции status и модифицировать его как мне нужно, получилось следующее:

<?php
class msCartProductHandler extends msCartHandler {
	
	public function status($data = array()) {	
		$status = array(
			'total_count' => 0
			,'total_cost' => 0
			,'total_weight' => 0
			,'cart' => $this->getProducts() // добавил елемент в массив "status" куда будет генерироваться "большая" корзина.
		);
		foreach ($this->cart as $item) {
			if (empty($item['ctx']) || $item['ctx'] == $this->modx->context->key){
				$status['total_count'] += $item['count'];
				$status['total_cost'] += $item['price'] * $item['count'];
				$status['total_weight'] += $item['weight'] * $item['count'];
			}
		}
		return array_merge($data, $status);
	}
}
Как можно заметить я добавил вывод функции getProducts, добавляем ее в наш модификатор и в итоге получаем такое его содержимое:

<?php
class msCartProductHandler extends msCartHandler {
	
	public function status($data = array()) {
		$status = array(
			'total_count' => 0
			,'total_cost' => 0
			,'total_weight' => 0
			,'cart' => $this->getProducts()
		);
		foreach ($this->cart as $item) {
			if (empty($item['ctx']) || $item['ctx'] == $this->modx->context->key){
				$status['total_count'] += $item['count'];
				$status['total_cost'] += $item['price'] * $item['count'];
				$status['total_weight'] += $item['weight'] * $item['count'];
			}
		}
		return array_merge($data, $status);
	}

	
	public function getProducts($cart) {
		$products = '';
		$cart = $this->get();
		
		if (!$this->modx->loadClass('pdofetch', MODX_CORE_PATH . 'components/pdotools/model/pdotools/', false, true)) {return false;}
		$pdoFetch = new pdoFetch($this->modx, $scriptProperties);

		$tplOuter = 'msCartOuter';
		$tplRow = 'msCartRow';		
		
		$products = array('goods' => '', 'total_count' => 0, 'total_weight' => 0, 'total_cost' => 0);
		foreach ($cart as $k => $v) {			
			$product = $this->modx->getObject('msProduct', $v['id']);
			$row['id'] = $product->get(id);
			$row['key'] = $k;
			$row['count'] = $v['count'];
			$row['pagetitle'] = $product->get('pagetitle');
			$row['old_price'] = $this->ms2->formatPrice(
				$row['price'] != $v['price']
					? $row['price']
					: $row['old_price']
			);
			$row['price'] = $this->ms2->formatPrice($v['price']);
			$row['weight'] = $this->ms2->formatWeight($v['weight']);
			$row['cost'] = $this->ms2->formatPrice($v['count'] * $v['price']);

			if (!empty($v['options']) && is_array($v['options'])) {
				foreach ($v['options'] as $key => $value) {
					$row['option.'.$key] = $value;
				}
			}
			unset($v['options']);

			$row['idx'] = $pdoFetch->idx++;	
			$products['goods'] .= empty($tplRow)
				? $pdoFetch->getChunk('', $row)
				: $pdoFetch->getChunk($tplRow, $row, $pdoFetch->config['fastMode']);
			$products['total_count'] += $v['count'];
			$products['total_cost'] +=  $v['count'] * $v['price'];
			$products['total_weight'] += $v['count'] * $v['weight'];
			
		}		
		
		$products['total_cost'] = $this->ms2->formatPrice($products['total_cost']);
		$products['total_weight'] = $this->ms2->formatWeight($products['total_weight']);

		return empty($tplOuter)
			? $pdoFetch->getChunk('', $products)
			: $pdoFetch->getChunk($tplOuter, $products, $pdoFetch->config['fastMode']);
	}	
	
}
Сохраняем файл. Переходим в систему управления, в настройки системы/minishop2/корзина и меняем класс обработчик корзины на msCartProductHandler.

В файле assets/components/minishop2/js/web/default.js после строки
miniShop2.Cart.totalCost = '.ms2_total_cost';
дописываем
miniShop2.Cart.totalProducts = '.ms2_total_products';
и после
$(miniShop2.Cart.totalCost).text(miniShop2.Utils.formatPrice(status['total_cost']));
пишем
$(miniShop2.Cart.totalProducts).html(status['cart']);

Осталось только обернуть вызов сниппета [[!msCart]] в блок с классом «ms2_total_products».
Роман Танаев
10 октября 2014, 10:25
modx.pro
31
9 077
+6

Комментарии: 28

Василий Наумкин
10 октября 2014, 14:26
0
Интересно, а какую проблему решал автор?
    Роман Танаев
    10 октября 2014, 14:27
    0
    аналогичную описанную тут modx.pro/help/3898/
      Василий Наумкин
      10 октября 2014, 14:30
      0
      Было бы неплохо дописать в начало заметки.

      Ну и редактировать default.js плохо — он перезапишется при обновлении.
        Роман Танаев
        10 октября 2014, 14:33
        0
        я вообще убрал предложение про проблему, а про default.js полностью согласен, на проекте где я использую данное решение, скрипт вообще не участвует т.к. создана его копия с глобальными доработками. Ну и в настройке системы путь до нового файла указан.
          Wassi Wassinen
          10 октября 2014, 16:40
          0
          В начало заметки добавьте какой функционал реализует это решение. А то так сразу и не поймешь. :) Спасибо.
          Волков Николай
          10 августа 2016, 13:12
          0
          Кстати на счет перезаписи при обновлении. Столкнулся с проектом в котором пришлось в стандартном классе msProduct поменять поле $allowChildResource с false на true, чтобы в дереве ресурсов у него можно было создавать дочерние ресурсы. При обновлении этот момент может слететь. Василий не подскажете, как этого избежать?
            Волков Николай
            10 августа 2016, 13:19
            0
            Понимаю, что по большему счету можно просто написать JS скриптик, который в дереве на node будет классы вешать, которые выпадающий список вернут. Но как это правильно делается на ExtJS понятия не имею, а криво писать нет желания абсолютно никакого.
        Павел Пустота
        12 октября 2014, 13:12
        0
        По-моему отличное решение. Попробовал.
        Для потомков оставлю, если хотите выводить ещё и картинку от товара, то в классе корзины нужно добавить:
        ...
        foreach ($cart as $k => $v) {
        ...
        	$row['thumb'] = $product->get('thumb'); // вот эту строку
        ...
        }
        ...
          Василий Столейков
          04 ноября 2014, 22:32
          0
          Сделал всё по инструкции.
          Не могу понять, почему выводит массив с данными, а не заменяет строки?
          Вот код, который выводится:
          Array ( [goods] => Array ( [id] => 9 [key] => fde9a248d43d903de47f1878b2004da4 [count] => 1 [pagetitle] => Ручка перьевая "Оптимист" [old_price] => 0 [price] => 340 [weight] => 0 [cost] => 340 [thumb] => /assets/images/products/9/120x90/01.jpg [idx] => 1 ) [total_count] => 1 [total_weight] => 0 [total_cost] => 340 )
          Как превратить этот массив в обычные строки?
            Роман Танаев
            05 ноября 2014, 09:48
            0
            А вы чанки указали? $tplOuter = '...'; и $tplRow = '...';
              Владимир Дремучий
              14 декабря 2014, 03:41
              0
              Да, столкнулся с такой же проблемой, выводит чисто массив, чанки указаны, делал так же все по инструкции. В логах такая ситуация
              [2014-12-14 03:39:05] (ERROR @ /home/d/dilladesign/store/public_html/core/components/minishop2/custom/cart/msсartproductрandler.class.php : 22) PHP warning: Missing argument 1 for msCartProductHandler::getProducts(), called in /home/d/dilladesign/store/public_html/core/components/minishop2/custom/cart/msсartproductрandler.class.php on line 9 and defined
              [2014-12-14 03:39:05] (ERROR @ /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdofetch.class.php : 18) Recoverable error: Argument 1 passed to pdoFetch::setConfig() must be an array, null given, called in /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdotools.class.php on line 39 and defined
              [2014-12-14 03:39:05] (ERROR @ /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdofetch.class.php : 46) PHP warning: array_merge() [<a href='function.array-merge'>function.array-merge</a>]: Argument #2 is not an array
              [2014-12-14 03:39:05] (ERROR @ /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdotools.class.php : 67) Recoverable error: Argument 1 passed to pdoTools::setConfig() must be an array, null given, called in /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdofetch.class.php on line 47 and defined
              [2014-12-14 03:39:05] (ERROR @ /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdotools.class.php : 81) PHP warning: array_merge() [<a href='function.array-merge'>function.array-merge</a>]: Argument #2 is not an array
              [2014-12-14 03:39:05] (ERROR @ /home/d/dilladesign/store/public_html/core/components/minishop2/custom/cart/msсartproductрandler.class.php : 22) PHP warning: Missing argument 1 for msCartProductHandler::getProducts(), called in /home/d/dilladesign/store/public_html/core/components/minishop2/custom/cart/msсartproductрandler.class.php on line 9 and defined
              [2014-12-14 03:39:05] (ERROR @ /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdofetch.class.php : 18) Recoverable error: Argument 1 passed to pdoFetch::setConfig() must be an array, null given, called in /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdotools.class.php on line 39 and defined
              [2014-12-14 03:39:05] (ERROR @ /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdofetch.class.php : 46) PHP warning: array_merge() [<a href='function.array-merge'>function.array-merge</a>]: Argument #2 is not an array
              [2014-12-14 03:39:05] (ERROR @ /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdotools.class.php : 67) Recoverable error: Argument 1 passed to pdoTools::setConfig() must be an array, null given, called in /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdofetch.class.php on line 47 and defined
              [2014-12-14 03:39:05] (ERROR @ /home/d/dilladesign/store/public_html/core/components/pdotools/model/pdotools/pdotools.class.php : 81) PHP warning: array_merge() [<a href='function.array-merge'>function.array-merge</a>]: Argument #2 is not an array
                Владимир Дремучий
                14 декабря 2014, 06:02
                0
                Я разобрался в чем дело. Проглядел про чанки и то что надо указывать те, которые есть в самом классе msCartProductHandler.
                $tplOuter = 'msCartOuter';
                $tplRow = 'msCartRow';
                Но в логах все равно записывается ошибка.
              Дмитрий
              07 октября 2016, 12:44
              0
              Здравствуйте, Вам удалось решить проблему?
              dapin
              05 февраля 2015, 09:03
              0
              Сделал все по инструкции, а в ответ белый экран. Уже всю голову сломал
                Роман Танаев
                05 февраля 2015, 16:38
                0
                А что в логах пишется?
                  dapin
                  06 февраля 2015, 11:29
                  0
                  в логах все чисто
                    dapin
                    06 февраля 2015, 11:29
                    0
                    попробовал на тестовом сайте, такая же ситуация
                      dapin
                      08 февраля 2015, 05:21
                      0
                      все сделал, но old_price=0 и после того как вставил строчку про картинку она не появилась, а в исходном коде пишется код как в чанке
                        Эдвард Ерохин
                        10 августа 2016, 12:30
                        0
                        Поделитесь пожалуйста информацией как белый экран побороли. Та же история, видимо что то упускаю

                        логи чисты…
                    Максим Кузнецов
                    10 июня 2015, 08:12
                    0
                    Все работает, только в лог сыпятся ошибки:

                    [2015-06-10 08:11:24] (ERROR @ /home/s2040/www/system_heart/components/minishop2/custom/cart/mscustomcarthandler.class.php : 30) PHP warning: Missing argument 1 for myCustomCart::getProducts(), called in /home/s2040/www/system_heart/components/minishop2/custom/cart/mscustomcarthandler.class.php on line 13 and defined
                    [2015-06-10 08:11:24] (ERROR @ /home/s2040/www/system_heart/components/pdotools/model/pdotools/pdofetch.class.php : 18) Recoverable error: Argument 1 passed to pdoFetch::setConfig() must be of the type array, null given, called in /home/s2040/www/system_heart/components/pdotools/model/pdotools/pdotools.class.php on line 41 and defined
                    [2015-06-10 08:11:24] (ERROR @ /home/s2040/www/system_heart/components/pdotools/model/pdotools/pdofetch.class.php : 45) PHP warning: array_merge(): Argument #2 is not an array
                    [2015-06-10 08:11:24] (ERROR @ /home/s2040/www/system_heart/components/pdotools/model/pdotools/pdotools.class.php : 51) Recoverable error: Argument 1 passed to pdoTools::setConfig() must be of the type array, null given, called in /home/s2040/www/system_heart/components/pdotools/model/pdotools/pdofetch.class.php on line 46 and defined
                    [2015-06-10 08:11:24] (ERROR @ /home/s2040/www/system_heart/components/pdotools/model/pdotools/pdotools.class.php : 66) PHP warning: array_merge(): Argument #2 is not an array
                  Артем
                  12 октября 2015, 17:06
                  0
                  Сделал все как написано, в ответ белый экран, а в логах вот это:

                  [2015-10-12 16:39:38] (ERROR @ /index.php) Unexpected tag 'id' in 98d45d5752e8b6d3778629a5b27f35d0 line 52, near '{id:' <- there
                  [2015-10-12 16:39:38] (ERROR @ /index.php) Unexpected tag 'id' in 98d45d5752e8b6d3778629a5b27f35d0 line 52, near '{id:' <- there
                  [2015-10-12 16:39:38] (ERROR @ /index.php) Unexpected tag 'id' in 98d45d5752e8b6d3778629a5b27f35d0 line 52, near '{id:' <- there
                  [2015-10-12 16:39:38] (ERROR @ /index.php) Unexpected tag 'id' in 98d45d5752e8b6d3778629a5b27f35d0 line 52, near '{id:' <- there
                  [2015-10-12 16:39:38] (ERROR @ /index.php) Unexpected tag 'id' in 98d45d5752e8b6d3778629a5b27f35d0 line 52, near '{id:' <- there
                  [2015-10-12 16:39:38] (ERROR @ /index.php) Unexpected tag 'id' in 98d45d5752e8b6d3778629a5b27f35d0 line 52, near '{id:' <- there
                  [2015-10-12 16:39:38] (ERROR @ /index.php) Unexpected tag 'id' in 98d45d5752e8b6d3778629a5b27f35d0 line 52, near '{id:' <- there
                  [2015-10-12 16:39:38] (ERROR @ /index.php) Unexpected tag 'id' in c154339fa7a364f0d071e960b902d8c5 line 52, near '{id:' <- there
                    Андрей Копп
                    25 октября 2015, 14:53
                    0
                    Для miniShop2 версии 2.3 alpha не подходит. Есть какое-то решение?
                      Виталий Барышников
                      06 марта 2016, 11:59
                      1
                      0
                      Спасибо, всё работает. Только для тех, кто еще будет делать была проблема, что не работает пересчет корзины когда меняем количество товара в input. Нужно вручную добавить событие сабмита формы в onchange этого инпута:
                      <input type="number" name="count" value="[[+count]]" max-legth="4" onchange="$(this).closest(miniShop2.form).submit();" class="input-sm form-control" />
                        Vbif
                        27 апреля 2016, 14:53
                        0
                        Здравствуйте. Подскажите пожалуйста, как решить проблему перезагрузки страницы, когда корзина становится пустой?
                          АндрейЧ
                          04 апреля 2017, 22:04
                          0
                          Здравствуйте. Но не могу понять что имел ввиду автор сообщения за 2014

                          Я разобрался в чем дело. Проглядел про чанки и то что надо указывать те, которые есть в самом классе msCartProductHandler.

                          $tplOuter = 'msCartOuter';
                          $tplRow = 'msCartRow';
                          В настройках сниппета msCart вижу что указан чанк tpl.msCart.Outer'
                          Неужели надо самому создать чанк msCartOuter, в настройках снипета заменить tpl.msCart.Outer на tpl.msCartOuter?

                            Константин
                            02 июля 2017, 04:52
                            0
                            Костыль, но всё же
                            <button onClick="setTimeout(function(){history.go(0);},0300);"></button>
                            Если страница грузится достаточно быстро, то можно избежать волокиты с дефолтными js.
                            Lori
                            18 июля 2021, 19:29
                            0
                            на текущий момент не актуально. сделал все, как описано, выводится стандартный сниппет со стандартными чанками
                              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                              28