[РЕШЕНО] Многоуровневая сортировка pdoResources

Добрый день!
Подскажите в какую сторону мыслить.
Имеется каталог товаров (генераторов). Необходимо настроить многоуровневую сортировку.
Все товары сортируются в первую очередь по мощности (TV поле) в порядке возрастания, в случае, если у двух товаров мощность одинаковая, то сначала должны строго выводится товары марки А, затем товары марки Б, а затем уже все остальные (марки так же прописываются в TV полях).
Каким образом это можно реализовать?
Наталья
24 августа 2016, 21:08
modx.pro
1 727
0

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

Сергей Шлоков
25 августа 2016, 09:30
+1
Попробуйте так (названия ТВ-шек условны)
&sortby=`{«TV.power»:«ASC»,«TV.firm»:«ASC»}`
    Наталья
    25 августа 2016, 10:21
    0
    да, это первый вариант, что приходит в голову, но он не обеспечит нужного порядка вывода фирм, так они должны выводиться не в стандартном порядке, а в заранее определенном — сначала фирма А, потом Б, потом остальные.
      Павел Гвоздь
      25 августа 2016, 10:35
      0
      Если направление сортировки ASC, то «Фирма А» будет перед «Фирма Б», т.к. по алфавиту буква «А» стоит перед «Б»…
      Если здесь имеется ввиду что-то иное, вроде того, что порядок сортировки фирм должен где-то задаваться вручную, то это стоит упомянуть в вопросе.
        Наталья
        25 августа 2016, 10:38
        0
        Фирма А и фирма Б — это условные названия, извиняюсь, если это ввело в заблуждение. Настоящий порядок следования фирм таков: ММЗ, ЯМЗ, ТМЗ, Ricardo, остальные фирмы.
          Павел Гвоздь
          25 августа 2016, 10:43
          0
          То бишь сортировка фирм должна указываться где-то вручную и она никак не может произвестись программно, не зная порядок расположения фирм?
            Наталья
            25 августа 2016, 10:45
            0
            Да, верно. Порядок следования фирм назначается вручную. В этом, собственно и вся сложность задачи.
              Павел Гвоздь
              25 августа 2016, 10:45
              0
              А фирмы где-то хранятся? Например, в ресурсах? Или они указываются вручную, в открытое для произвольного редактирования, поле?
                Наталья
                25 августа 2016, 10:47
                0
                значения фирм заполняются в ТВ поля при создании / редактировании ресурса.
                  Павел Гвоздь
                  25 августа 2016, 10:58
                  +1
                  1) Фирмы надо где-то хранить и там-же указывать их порядок (например menuindex в дереве ресурсов).

                  2) При добавлении/редактировании ресурса в ТВ типа «Список (одиночный выбор)» выбирать нужную фирму.

                  3) В ТВ, на вкладке «Параметры ввода», помимо типа «Список (одиночный выбор)» также необходимо в поле «Возможные значения» указать PHP запрос выборки списка фирм из дерева ресурсов. PHP запрос там указывается таким образом:
                  @EVAL return 'value_1==display_1||value_2==display_2';
                  Только вместо return '...'; подставляем свои значения фирм, полученные путём выборки из дерева ресурсов.

                  4) Сделать запрос с Join-ами, который выберет список фирм из дерева ресурсов, приджоинит ТВ value, соответствующее значению названия фирмы, а также приджоинит ресурс, узнав его id из таблицы значения ТВ. Тогда можно будет отсортировать так, как нужно.
                  Не уверен, что порядок джоинов верный, возможно можно сделать правильнее, надо на практике проверять.
                    Наталья
                    25 августа 2016, 11:05
                    0
                    -
                      Павел Гвоздь
                      25 августа 2016, 11:10
                      0
                      Тем не менее, вариант, который я описал, считаю более приемлемым в данной ситуации. Я бы решил задачу так (хотя, с радостью выслушаю мнения других участников сообщества, как бы они решили данную задачу).

                      Еще один осложняющий момент — подобная сортировка нужно только в одной подкатегории каталога, в остальных не нужно. Таково желание заказчика…
                      Ну, тут я думаю разобраться не сложно, как сделать проверку нужной подкатегории и подстановку необходимого вызова сниппета. Вообще, советую использовать Fenom для таких целей, т.к. проверку будет сделать очень просто.
                      Ну или по разным шаблонам, в крайнем случае, раскидать.
                      Наталья
                      25 августа 2016, 11:20
                      0
                      Сделать запрос с Join-ами, который выберет список фирм из дерева ресурсов, приджоинит ТВ value, соответствующее значению названия фирмы, а также приджоинит ресурс, узнав его id из таблицы значения ТВ. Тогда можно будет отсортировать так, как нужно.


                      Хоть опыта построения Join запросов у меня мало, но основная суть вроде бы ясна — в итоге мы получим список фирм с соответствующими им ресурсами, верно?
                      А вот как это потом отсортировать в нужном порядке мне непонятно :(
                      Павел Гвоздь
                      25 августа 2016, 13:52
                      0
                      Можно сюда отписаться, как что-то сделаешь. Дальше будем отталкиваться от того, что у тебя получилось.
                      Наталья
                      26 августа 2016, 16:29
                      +2
                      Предполагаю, что с моей стороны это велосипед и буду очень рада выслушать конструктивную критику, но тем не менее задача решена.

                      Основная суть подхода заключается в назначении флагов приоритетности для нужных нам двигателей. Затем производим сортировку многомерного массива по двум полям. И в конце просто скармливаем полученный список id ресурсов сниппету.

                      $resources = $modx->getCollection('modResource', array('parent' => 517));
                      
                      $m_d = array();
                      
                      foreach ($resources as $resource) {
                          $id = $resource->get('id');
                          $m = $resource->getTVValue(20) + 0; // значение ТВ мощность
                          $d = $resource->getTVValue(34); // значение ТВ двигатель
                          // назначаем приоритетность двигателю
                          switch ($d) {
                              case '40':
                                  $priority = 4;
                                  break;
                              case '38':
                                  $priority = 3;
                                  break;
                              case '39':
                                  $priority = 2;
                                  break;
                              case '42':
                                  $priority = 1;
                                  break;
                              default:
                                  $priority = 0;
                          }
                          $m_d[] = array(
                              'id' => $id,
                              'value' => array(
                                  'm' => $m,
                                  'd' => $d,
                                  'priority' => $priority
                              )
                          );
                      }
                      
                      $ar_sort_m = array();
                      $ar_sort_priority = array();
                      
                      foreach ($m_d as &$ar_item) {
                          $ar_sort_m[] = $ar_item['value']['m']; //Выбираем первое поле, по которому будем сортировать массив
                          $ar_sort_priority[] = $ar_item['value']['priority'];//Выбираем второе поле, по которому будем сортировать массив
                      }
                      
                      array_multisort($ar_sort_m, SORT_ASC, $ar_sort_priority, SORT_DESC, $m_d);
                      
                      // Формируем список ресурсов в нужном нам порядке
                      foreach ($m_d as $key => $value) {
                          $ids .= $value['id'] . ',';
                      }
                      
                      $params = array(
                          'resources' => $ids,
                          'limit' => $limit,
                          'tpl' => $tpl,
                          'select' => 'id,pagetitle,introtext,content',
                          'includeTVs' => $fields,
                          'showHidden' => '1',
                          'sortby' => ''
                      );
                      
                      $result = $modx->runSnippet('pdoResources', $params);
                      Павел Гвоздь
                      27 августа 2016, 09:02
                      +1
                      Ну, можно воспользоваться не getCollection, а getIterator.
                      Наталья
                      27 августа 2016, 13:28
                      0
                      спасибо, будет время, попробую переписать.
                      Павел Гвоздь
                      27 августа 2016, 13:30
                      1
                      +1
                      А там всего лишь заменить getCollection на getIterator. Вот здесь есть статья об этом.
                      Наталья
                      27 августа 2016, 13:32
                      0
                      о! Здорово, почитаю. До этого не приходилось с итератором иметь дела. Интересно!
                    Наталья
                    25 августа 2016, 11:05
                    0
                    Не совсем поняла предыдущий вопрос, поэтому неправильно на него ответила. Да, фирмы хранятся в возможных значениях ТВ в виде ММЗ==1||ЯМЗ==2||Ricardo==3 и т.п. (цифры приведены для примера, по факту они другие и следуют не в таком порядке). Тип ввода стоит Список (одиночный выбор).
                    Еще один осложняющий момент — подобная сортировка нужно только в одной подкатегории каталога, в остальных не нужно. Таково желание заказчика…
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    19