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

Вот многие сравнивают 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 16:33

Круто!

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

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

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

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

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

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

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

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

Я же говорю:

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

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

CoraloReefВячеслав Сергееевич
01.11.2013 16: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 16:32

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

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

CoraloReefВячеслав Сергееевич
01.11.2013 17: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 17:25

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

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

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

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

Peter Zenin
01.11.2013 02:07

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

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

Благодарю!

Андрей
31.07.2014 21:05

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

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

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


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

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

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

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

born2slip
pishnaa istntome
22.11.2022 14:06
огромное спасибо! )
inetlover
Александр Наумов
14.11.2022 10:19
посмотри документацию. Спасибо, что-то она мне не нагуглилась. Это просто функции объединения для о...
bezumkin
Василий Наумкин
10.11.2022 05:46
Спасибо за поздравления!
inetlover
Александр Наумов
09.11.2022 17:08
Посмотрел в ДевТулсе свойство overscroll-behavior: none; присутствует, проверил в Chrome и Chromium ...
bezumkin
Василий Наумкин
03.11.2022 20:57
Поискать в исходниках ссылки на её адрес и поменять - скорее всего только nuxt.config.js. А зачем эт...
ni.kolokol@mail.ru
Николай Каленников
03.11.2022 19:43
Спасибо. Попробую тоже с нуля переставить
inetlover
Александр Наумов
03.11.2022 19:24
Спасибо!!! Все заработало!
bezumkin
Василий Наумкин
28.10.2022 05:23
В тексте есть подсказка // Контроллер требует новое разрешение protected $scope = 'ord...
bezumkin
Василий Наумкин
27.10.2022 13:25
Понял, спасибо!
inetlover
Александр Наумов
23.10.2022 13:33
Понял, спасибо!