Добавляем "Цена от" для категории miniShop2

В некоторых моих сайтах-магазинах я отображаю в списке категорий цену в формате «от XXX руб.», вот так:



Небольшая инструкция, как я это делаю:

1. Создаем доп поле с именем categoryFromPrice и назначаем его для категорий. Тип ввода — число.

2. Создаем плагин с именем UpdateCategoryFromPrice на событие OnDocFormSave:

<?php
if($resource->get('class_key') == 'msProduct') {
  $parent = $modx->getObject('msCategory', $resource->get('parent'));

  // вычисляем минимальную цену в категории товара
  $minPrice = 0;
  $products = $modx->getCollection('msProduct', array('published' => 1, 'deleted' => 0, 'parent' => $parent->get('id')));
  foreach($products as $product) {
    $productPrice = $product->get('price');
    if($minPrice == 0 || $productPrice < $minPrice) {
      $minPrice = $productPrice;
    }
  }
  
  // задаем эту цену для категории-родителя
  $parent->setTVValue('categoryFromPrice', $minPrice);
  $parent->save();
  
  // а теперь для всех категорий выше
  $doCycle = true;
  while($doCycle) {
    $minPrice = 0;
    $parent = $modx->getObject('msCategory', $parent->get('parent'));
    if($parent) {
      $childCategories = $modx->getCollection('msCategory', array('published' => 1, 'deleted' => 0, 'parent' => $parent->get('id')));
      foreach($childCategories as $childCategory) {
        $categoryPrice = floatval($childCategory->getTVValue('categoryFromPrice'));
        if($categoryPrice !=0 && ($minPrice == 0 || $categoryPrice < $minPrice)) {
          $minPrice = $categoryPrice;
        };
      }
      $parent->setTVValue('categoryFromPrice', $minPrice);
      $parent->save();
    }
    else {
      $doCycle = false;
    }
  }
  
}
3. Используем categoryFromPrice где нам нужно, в частности в списке категорий.

Вот такое небольшое решение, может кому пригодится. Ну и как минимум сам буду пользоваться =)

И да, это не оптимальное по скорости решение, если у вас много товаров (> нескольких сотен), то могут быть проблемы с производительностью.
Наумов Алексей
17 февраля 2016, 08:36
modx.pro
31
5 448
+8

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

Wassi Wassinen
17 февраля 2016, 13:02
0
Ради интереса сравни кол-во операций с простым вызовом:

[[msProducts &limit=`1` &sortby=`price` &tpl=`@INLINE {{+price}}` &parents=`{{+id}}`]]
    Наумов Алексей
    17 февраля 2016, 13:58
    +2
    Не люблю такое вот вычисление на лету, больше нравиться немного кешировать такие вещи.
    Сортировочку потом можно сделать.
    Кирилл
    17 февраля 2016, 13:08
    1
    +3
    А зачем вычислять минимальную цену перебором всех товаров? Можно через xPDO выбрать MIN(value), наверное вот так:

    $q = $modx->newQuery('msProduct');
    $q->select("MIN(price) AS min_price");
    $q->where(array(
    	'published' => 1,
    	'deleted' => 0,
    	'price:>' => 0,
    	'parent' => $parent->get('id')
    ));
    if ($q->prepare() && $q->stmt->execute()) {
        $arr = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    $minPrice = $arr[0]['min_price'];
    Илья Уткин
    17 февраля 2016, 13:20
    1
    +3
    Необязательно выбирать из базы все товары, чтобы узнать, у какого же из них самая низкая цена.
    $q = $modx->newQuery('msProductData', array('id:>' => 0));
    $q->select('MIN(price) as min_price');
    $q->leftJoin('msProduct', 'Product', 'Product.id = msProductData.id');
    $q->where(array('Product.parent' => $parent->get('id')));
    $q->prepare();
    $q->stmt->execute();
    $res = $q->stmt->fetch();
    $minPrice = $res['min_price'];
      Степан Прищепенко
      29 февраля 2016, 11:11
      0
      если категории вложены друг в друга то лучше получить вначале id всех соответствующих документов через getChildIds иначе вывод будет не верный.
        Роман
        04 июля 2018, 21:09
        0
        Можно это сделать без miniShop2 !?

        У меня пять разных категорий, и для каждой нужно указать в отдельности.
      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
      7