[РЕШЕНО] Многоуровневая сортировка pdoResources
Добрый день!
Подскажите в какую сторону мыслить.
Имеется каталог товаров (генераторов). Необходимо настроить многоуровневую сортировку.
Все товары сортируются в первую очередь по мощности (TV поле) в порядке возрастания, в случае, если у двух товаров мощность одинаковая, то сначала должны строго выводится товары марки А, затем товары марки Б, а затем уже все остальные (марки так же прописываются в TV полях).
Каким образом это можно реализовать?
Подскажите в какую сторону мыслить.
Имеется каталог товаров (генераторов). Необходимо настроить многоуровневую сортировку.
Все товары сортируются в первую очередь по мощности (TV поле) в порядке возрастания, в случае, если у двух товаров мощность одинаковая, то сначала должны строго выводится товары марки А, затем товары марки Б, а затем уже все остальные (марки так же прописываются в TV полях).
Каким образом это можно реализовать?
Комментарии: 19
Попробуйте так (названия ТВ-шек условны)
&sortby=`{«TV.power»:«ASC»,«TV.firm»:«ASC»}`
да, это первый вариант, что приходит в голову, но он не обеспечит нужного порядка вывода фирм, так они должны выводиться не в стандартном порядке, а в заранее определенном — сначала фирма А, потом Б, потом остальные.
Если направление сортировки ASC, то «Фирма А» будет перед «Фирма Б», т.к. по алфавиту буква «А» стоит перед «Б»…
Если здесь имеется ввиду что-то иное, вроде того, что порядок сортировки фирм должен где-то задаваться вручную, то это стоит упомянуть в вопросе.
Если здесь имеется ввиду что-то иное, вроде того, что порядок сортировки фирм должен где-то задаваться вручную, то это стоит упомянуть в вопросе.
Фирма А и фирма Б — это условные названия, извиняюсь, если это ввело в заблуждение. Настоящий порядок следования фирм таков: ММЗ, ЯМЗ, ТМЗ, Ricardo, остальные фирмы.
То бишь сортировка фирм должна указываться где-то вручную и она никак не может произвестись программно, не зная порядок расположения фирм?
Да, верно. Порядок следования фирм назначается вручную. В этом, собственно и вся сложность задачи.
А фирмы где-то хранятся? Например, в ресурсах? Или они указываются вручную, в открытое для произвольного редактирования, поле?
значения фирм заполняются в ТВ поля при создании / редактировании ресурса.
1) Фирмы надо где-то хранить и там-же указывать их порядок (например menuindex в дереве ресурсов).
2) При добавлении/редактировании ресурса в ТВ типа «Список (одиночный выбор)» выбирать нужную фирму.
3) В ТВ, на вкладке «Параметры ввода», помимо типа «Список (одиночный выбор)» также необходимо в поле «Возможные значения» указать PHP запрос выборки списка фирм из дерева ресурсов. PHP запрос там указывается таким образом:
4) Сделать запрос с Join-ами, который выберет список фирм из дерева ресурсов, приджоинит ТВ value, соответствующее значению названия фирмы, а также приджоинит ресурс, узнав его id из таблицы значения ТВ. Тогда можно будет отсортировать так, как нужно.
Не уверен, что порядок джоинов верный, возможно можно сделать правильнее, надо на практике проверять.
2) При добавлении/редактировании ресурса в ТВ типа «Список (одиночный выбор)» выбирать нужную фирму.
3) В ТВ, на вкладке «Параметры ввода», помимо типа «Список (одиночный выбор)» также необходимо в поле «Возможные значения» указать PHP запрос выборки списка фирм из дерева ресурсов. PHP запрос там указывается таким образом:
@EVAL return 'value_1==display_1||value_2==display_2';
Только вместо return '...'; подставляем свои значения фирм, полученные путём выборки из дерева ресурсов.4) Сделать запрос с Join-ами, который выберет список фирм из дерева ресурсов, приджоинит ТВ value, соответствующее значению названия фирмы, а также приджоинит ресурс, узнав его id из таблицы значения ТВ. Тогда можно будет отсортировать так, как нужно.
Не уверен, что порядок джоинов верный, возможно можно сделать правильнее, надо на практике проверять.
-
Тем не менее, вариант, который я описал, считаю более приемлемым в данной ситуации. Я бы решил задачу так (хотя, с радостью выслушаю мнения других участников сообщества, как бы они решили данную задачу).
Ну или по разным шаблонам, в крайнем случае, раскидать.
Еще один осложняющий момент — подобная сортировка нужно только в одной подкатегории каталога, в остальных не нужно. Таково желание заказчика…Ну, тут я думаю разобраться не сложно, как сделать проверку нужной подкатегории и подстановку необходимого вызова сниппета. Вообще, советую использовать Fenom для таких целей, т.к. проверку будет сделать очень просто.
Ну или по разным шаблонам, в крайнем случае, раскидать.
Сделать запрос с Join-ами, который выберет список фирм из дерева ресурсов, приджоинит ТВ value, соответствующее значению названия фирмы, а также приджоинит ресурс, узнав его id из таблицы значения ТВ. Тогда можно будет отсортировать так, как нужно.
Хоть опыта построения Join запросов у меня мало, но основная суть вроде бы ясна — в итоге мы получим список фирм с соответствующими им ресурсами, верно?
А вот как это потом отсортировать в нужном порядке мне непонятно :(
Можно сюда отписаться, как что-то сделаешь. Дальше будем отталкиваться от того, что у тебя получилось.
Предполагаю, что с моей стороны это велосипед и буду очень рада выслушать конструктивную критику, но тем не менее задача решена.
Основная суть подхода заключается в назначении флагов приоритетности для нужных нам двигателей. Затем производим сортировку многомерного массива по двум полям. И в конце просто скармливаем полученный список id ресурсов сниппету.
Основная суть подхода заключается в назначении флагов приоритетности для нужных нам двигателей. Затем производим сортировку многомерного массива по двум полям. И в конце просто скармливаем полученный список 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);
Ну, можно воспользоваться не getCollection, а getIterator.
спасибо, будет время, попробую переписать.
А там всего лишь заменить getCollection на getIterator. Вот здесь есть статья об этом.
о! Здорово, почитаю. До этого не приходилось с итератором иметь дела. Интересно!
Не совсем поняла предыдущий вопрос, поэтому неправильно на него ответила. Да, фирмы хранятся в возможных значениях ТВ в виде ММЗ==1||ЯМЗ==2||Ricardo==3 и т.п. (цифры приведены для примера, по факту они другие и следуют не в таком порядке). Тип ввода стоит Список (одиночный выбор).
Еще один осложняющий момент — подобная сортировка нужно только в одной подкатегории каталога, в остальных не нужно. Таково желание заказчика…
Еще один осложняющий момент — подобная сортировка нужно только в одной подкатегории каталога, в остальных не нужно. Таково желание заказчика…
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.