Вывод категорий с присоединением товара

Вот многие сравнивают pdoTools с другими сниппетами, забывая, что сравнивать можно не только скорость, но и возможности.

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

В итоге выходит вот такой листинг раздела товаров:

Конечно, вызов сниппета довольно сложный, и местами похож на извращение, но работает.

[[!msProducts?
    &class=`msCategory`
    &parents=`2`
    &where=`{"class_key":"msCategory"}`
    &tpl=`tpl.Products.category_light`
    &tplOdd=`tpl.Products.category_dark`
    &select=`{
        "msCategory":"*"
        ,"msProduct":"msProduct.id as product_id, msProduct.uri as product_uri, msProduct.pagetitle as product_pagetitle"
        ,"msProductData":"*"
        ,"500x500":"500x500.url as 500x500"
    }`
    &innerJoin=`{
        "msProduct": {"class":"msProduct", "alias":"msProduct", "on":"msProduct.parent = msCategory.id AND msProduct.class_key = 'msProduct'"}
        ,"msProductData": {"class":"msProductData", "alias":"msProductData", "on":"msProduct.id = msProductData.id"}
    }`
    &leftJoin=`{
        "500x500": {"class":"msProductFile","alias":"500x500", "on": "500x500.product_id = msProduct.id AND 500x500.path LIKE '%/500x500/' AND 500x500.rank=0"}
    }`
    &sortby=`msCategory.menuindex`
    &sortdir=`asc`
    &showLog=`1`
]]

А что там со скоростью, при такой выборке?


0.0000942: xPDO query object created
0.0003920: innerJoined msProduct as msProduct
0.0003672: innerJoined msProductData as msProductData
0.0003479: leftJoined msProductData as Data
0.0003240: leftJoined msVendor as Vendor
0.0003240: leftJoined msProductFile as 500x500
0.0000072: Grouped by msCategory.id
0.0003371: Added selection of msCategory: SQL_CALC_FOUND_ROWS `id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `content`, `richtext`, `template`, `menuindex`, `searchable`, `cacheable`, `createdby`, `createdon`, `editedby`, `editedon`, `deleted`, `deletedon`, `deletedby`, `publishedon`, `publishedby`, `menutitle`, `donthit`, `privateweb`, `privatemgr`, `content_dispo`, `hidemenu`, `class_key`, `context_key`, `content_type`, `uri`, `uri_override`, `hide_children_in_tree`, `show_in_tree`, `properties`
0.0000482: Added selection of Data: `article`, `price`, `old_price`, `weight`, `image`, `thumb`, `vendor`, `made_in`, `new`, `popular`, `favorite`, `tags`, `color`, `size`, `source`
0.0000441: Added selection of Vendor: `name` AS `vendor.name`, `resource` AS `vendor.resource`, `country` AS `vendor.country`, `logo` AS `vendor.logo`, `address` AS `vendor.address`, `phone` AS `vendor.phone`, `fax` AS `vendor.fax`, `email` AS `vendor.email`, `description` AS `vendor.description`, `properties` AS `vendor.properties`
0.0004640: Added selection of msProduct: msProduct.id as product_id, msProduct.uri as product_uri, msProduct.pagetitle as product_pagetitle AS 0
0.0002091: Added selection of msProductData: `id`, `article`, `price`, `old_price`, `weight`, `image`, `thumb`, `vendor`, `made_in`, `new`, `popular`, `favorite`, `tags`, `color`, `size`, `source`
0.0000339: Added selection of 500x500: 500x500.url as 500x500
0.0014851: Processed additional conditions
0.0023470: Added where condition: class_key=msCategory, msCategory.parent:IN(2,15,16,17,18,19,20,21,26,28,22,27,29,30,31,32,33), OR:msCategory.id:IN(22), msCategory.published=1, msCategory.deleted=0
0.0000241: Sorted by msCategory.menuindex, asc
0.0000091: Limited to 10, offset 0
0.0008841: SQL prepared "SELECT SQL_CALC_FOUND_ROWS `msCategory`.`id`, `msCategory`.`type`, `msCategory`.`contentType`, `msCategory`.`pagetitle`, `msCategory`.`longtitle`, `msCategory`.`description`, `msCategory`.`alias`, `msCategory`.`link_attributes`, `msCategory`.`published`, `msCategory`.`pub_date`, `msCategory`.`unpub_date`, `msCategory`.`parent`, `msCategory`.`isfolder`, `msCategory`.`introtext`, `msCategory`.`content`, `msCategory`.`richtext`, `msCategory`.`template`, `msCategory`.`menuindex`, `msCategory`.`searchable`, `msCategory`.`cacheable`, `msCategory`.`createdby`, `msCategory`.`createdon`, `msCategory`.`editedby`, `msCategory`.`editedon`, `msCategory`.`deleted`, `msCategory`.`deletedon`, `msCategory`.`deletedby`, `msCategory`.`publishedon`, `msCategory`.`publishedby`, `msCategory`.`menutitle`, `msCategory`.`donthit`, `msCategory`.`privateweb`, `msCategory`.`privatemgr`, `msCategory`.`content_dispo`, `msCategory`.`hidemenu`, `msCategory`.`class_key`, `msCategory`.`context_key`, `msCategory`.`content_type`, `msCategory`.`uri`, `msCategory`.`uri_override`, `msCategory`.`hide_children_in_tree`, `msCategory`.`show_in_tree`, `msCategory`.`properties`, `Data`.`article`, `Data`.`price`, `Data`.`old_price`, `Data`.`weight`, `Data`.`image`, `Data`.`thumb`, `Data`.`vendor`, `Data`.`made_in`, `Data`.`new`, `Data`.`popular`, `Data`.`favorite`, `Data`.`tags`, `Data`.`color`, `Data`.`size`, `Data`.`source`, `Vendor`.`name` AS `vendor.name`, `Vendor`.`resource` AS `vendor.resource`, `Vendor`.`country` AS `vendor.country`, `Vendor`.`logo` AS `vendor.logo`, `Vendor`.`address` AS `vendor.address`, `Vendor`.`phone` AS `vendor.phone`, `Vendor`.`fax` AS `vendor.fax`, `Vendor`.`email` AS `vendor.email`, `Vendor`.`description` AS `vendor.description`, `Vendor`.`properties` AS `vendor.properties`, msProduct.id as product_id, msProduct.uri as product_uri, msProduct.pagetitle as product_pagetitle, `msProductData`.`id`, `msProductData`.`article`, `msProductData`.`price`, `msProductData`.`old_price`, `msProductData`.`weight`, `msProductData`.`image`, `msProductData`.`thumb`, `msProductData`.`vendor`, `msProductData`.`made_in`, `msProductData`.`new`, `msProductData`.`popular`, `msProductData`.`favorite`, `msProductData`.`tags`, `msProductData`.`color`, `msProductData`.`size`, `msProductData`.`source`, 500x500.url as 500x500 FROM `modx_site_content` AS `msCategory` JOIN `modx_site_content` `msProduct` ON msProduct.parent = msCategory.id AND msProduct.class_key = 'msProduct' JOIN `modx_ms2_products` `msProductData` ON msProduct.id = msProductData.id LEFT JOIN `modx_ms2_products` `Data` ON `msCategory`.`id`=`Data`.`id` LEFT JOIN `modx_ms2_vendors` `Vendor` ON `Data`.`vendor`=`Vendor`.`id` LEFT JOIN `modx_ms2_product_files` `500x500` ON 500x500.product_id = msProduct.id AND 500x500.path LIKE '%/500x500/' AND 500x500.rank=0 WHERE  ( `msCategory`.`class_key` = 'msCategory' AND  ( `msCategory`.`parent` IN (2,15,16,17,18,19,20,21,26,28,22,27,29,30,31,32,33) OR `msCategory`.`id` IN (22) )  AND `msCategory`.`published` = 1 AND `msCategory`.`deleted` = 0 )  GROUP BY msCategory.id ORDER BY msCategory.menuindex asc LIMIT 10 "
0.0002890: SQL executed
0.0002091: Total rows: 5
0.0001891: Rows fetched
0.0005128: Returning raw data
0.0012262: Checked the active modifiers
0.0019169: Loaded chunk "tpl.Products.category_light"
0.0025079: Loaded chunk "tpl.Products.category_dark"
0.0022061: Returning processed chunks
0.0184011: Total time
19 660 800: Memory usage

2 сотых секунды.

Имейте в виду, что сниппеты pdoTools умеют и так.

Учитывая общее ядро, вот этот конкретный вызов работает и в pdoResources и в msProducts, но второй сниппет более предпочтителен для товаров, так как он форматирует цены.

В принципе, схожим образом можно выводить и категории новостей, и другие разделы сайта.

Комментарии (15)
CoraloReefВячеслав Сергееевич
31.10.2013 08:33

Круто!

А можно ли сделать обратное? Например, есть такое дерево:

-Новостройки
--ЖК1
---квартира1
---квартира2
---квартира3
--ЖК2
---квартира1
---квартира2
---квартира3
---квартира4

Можно ли искать по квартирам, а выводить ЖК? Для чего это нужно: на странице Новостройки организую mfilter2, который по определенным параметрам будет искать квартиры, но выводить результат будет в виде ЖК ?

bezumkinВасилий Наумкин
31.10.2013 08:36

Я думаю, можно присоединить категорию к товару и сгруппировать по ней.

CoraloReefВячеслав Сергееевич
31.10.2013 09:14

Сейчас так и сделано - ЖК - категория, квартира - товар. Ищу по квартирам, вывожу (через pdoField) ЖК. Но загвостка в том, что выводится ровно столько ЖК, сколько и квартир. А хотелось бы по одному. Т.е. фильтр нашел квартиры у одного ЖК и вывел один ЖК, а не множество одних и тех же ЖК... Реально такое реализовать? Или только сниппет пилить?

bezumkinВасилий Наумкин
31.10.2013 09:15

Я же говорю:

&groupby=`msCategory.id`
CoraloReefВячеслав Сергееевич
31.10.2013 09:25

Вот не знал об этом... Спасибо! В очередной раз=)

CoraloReefВячеслав Сергееевич
01.11.2013 08:25

Дошло дело до реализации и попал в тупик... Вызываю так:

[[!msProducts?
    &parents=`22`
    &limit=`50`
    &groupby=`msCategory.id`
    &tpl=`test.tpl.obj.item`
    &showLog=`1`
]]

В итоге ничего не выводится, а в логе ошибка:

0.0005949: Could not process query, error #1054: Unknown column 'msCategory.id' in 'group statement'

Где я натупил?

bezumkinВасилий Наумкин
01.11.2013 08:32

Слава, сравни вызов в заметке и свой.

Мне кажется, у тебя чего то не хватает.

CoraloReefВячеслав Сергееевич
01.11.2013 09:01

Не весь код в заметке понял. Попытался вызвать так:

[[!msProducts?
    &class=`msCategory`
    &where=`{"class_key":"msCategory"}`
    &parents=`22`
    &limit=`50`
    &groupby=`msCategory.id`
    &select=`{
    "msCategory":"*"
    ,"msProduct":"msProduct.id as product_id, msProduct.uri as product_uri, msProduct.pagetitle as product_pagetitle"
    ,"msProductData":"*"
    }`
   &innerJoin=`{
    "msProduct": {"class":"msProduct", "alias":"msProduct", "on":"msProduct.parent = msCategory.id AND msProduct.class_key = 'msProduct'"}
    ,"msProductData": {"class":"msProductData", "alias":"msProductData", "on":"msProduct.id = msProductData.id"}
    }`
    &tpl=`test.tpl.obj.item`
    &showLog=`1`
    &sortby=`msCategory.menuindex`
    &sortdir=`asc`
]]

Так появляются категории, но теперь думаю, сниппет действительно сгруппировал товары по категориям или просто вывел список категорий?

bezumkinВасилий Наумкин
01.11.2013 09:25

Выбирать нужно товары, а к ним присоединять категории.

У тебя сйечас наоборот.

Станислав
20.04.2014 12:52

Здравствуйте, Василий вы не могли бы расписать подробнее, вызов сниппета, что к чему и зачем, неделю мучаюсь не могу понять. Спасибо

Peter Zenin
31.10.2013 18:07

Василий, приветствую! Извинюсь, что не в тему... Ты писал /assets/components/minishop2/js/web/default.js ? Не подскажешь, где почитать про используемую в скрипте систему каллбэков? Или не подскажешь вкратце (если это возможно) как оно в скрипте работает?

bezumkinВасилий Наумкин
31.10.2013 19:02
Peter Zenin
31.10.2013 19:58

Благодарю!

Андрей
31.07.2014 13:05

Присоединяюсь к Станиславу. Василий, можете расписать подробнее объяснить?

Максим Степанов
28.09.2014 13:39

Здравствуйте, подскажите как можно вывести вот так:


Категория-1
Товар, Товар, Товар, Товар

Категория-2
Товар, Товар, Товар, Товар

Категория-3
Товар, Товар, Товар, Товар

Пример сайта http://www.dns-shop.ru/catalog/29/komplektuyushhie-k-pk/

ЕвгенийК
09.04.2022 03:35
Это хорошо, что такая возможность есть и может быть использована. А то тенденция, мания, что-то в по...
begoodco1
07.04.2022 05:49
Зарегистрировался чтобы выразить благодарность за доступное и подробное описание процесса. Была возм...
bezumkin
Василий Наумкин
18.03.2022 12:35
Авторизация есть из коробки, для входа в базовую админку. Можно установить через composer и собрать ...
bezumkin
Василий Наумкин
10.03.2022 12:08
Ну, я имел в виду, что по закону можно =) А в реальности с валютой очевидные проблемы.
Сергей Лелеко
04.03.2022 06:12
О как! не знал! спасибо
bezumkin
Василий Наумкин
01.03.2022 15:32
Я делал одного бота на botman/botman, но из-за своей универсальности конкретно с Телеграм на нём раб...
bezumkin
Василий Наумкин
25.02.2022 09:22
P.S. Кажется цитаты у тебя никак не стилизуются в комментариях... Спасибо, поправил!
Electrica
Михаил
08.02.2022 11:19
Работает!
Алексей
09.01.2019 10:55
Насыщенный год ) От души поздравляю с ДР! Счастья, успехов и семейного благополучия! Жаль лимит заме...
septa rose
28.05.2018 22:16
hmmm, keren abis