[РЕШЕНО] Сложное where в msProducts

Задача такая: на странице товара вывести блок с товарами, которые имею цену (price) равную текущему товару или сделаны (made_in) там же где текущий товар, если таковых нет, вывести два любых товара из той же категории, что и текущий товар.
Соответственно вызвал сниппет msProducts
{'msProducts' | snippet: [
                'includeTVs' => 'catalog_images,logo_franchise,abs_views,priority',
                'limit' => 2,
                'tpl' =>  '@FILE chunks/filters/filterResultRow.html',
                'where' => ['msProduct.id:!=' => $id,'msProduct.parent' => $parent,'msProduct.published' => 1,'msProduct.deleted' => 0,'OR:Data.made_in:=' => $madeIn, 'OR:Data.price:=' => $price],
                'showLog' => 1
            ]}
вот лог

0.0000389: pdoTools loaded. 0.0001361: Conditions prepared 0.0000150: xPDO query object created 0.0002639: Included list of tvs: abs_views, catalog_images, logo_franchise, priority 0.0000811: leftJoined msProductData as Data 0.0000470: leftJoined msVendor as Vendor 0.0000460: leftJoined modTemplateVarResource as TVabs_views 0.0000598: leftJoined modTemplateVarResource as TVcatalog_images 0.0000420: leftJoined modTemplateVarResource as TVlogo_franchise 0.0000410: leftJoined modTemplateVarResource as TVpriority 0.0000010: Grouped by msProduct.id 0.0000551: Added selection of msProduct: `id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `alias_visible`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `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.0000331: Added selection of msProductData: `article`, `price`, `old_price`, `weight`, `image`, `thumb`, `vendor`, `made_in`, `new`, `popular`, `favorite`, `tags`, `color`, `size`, `source`, `own_firm`, `franchise_firm`, `lump_sum`, `royalty`, `payback`, `contact_person`, `phone_number`, `email_address`, `promo`, `place` 0.0000279: Added selection of msVendor: `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.0000050: Added selection of modTemplateVarResource: IFNULL(`value`, '0') AS `abs_views` 0.0000041: Added selection of modTemplateVarResource: IFNULL(`value`, '') AS `catalog_images` 0.0000029: Added selection of modTemplateVarResource: IFNULL(`value`, '') AS `logo_franchise` 0.0000029: Added selection of modTemplateVarResource: IFNULL(`value`, '') AS `priority` 0.0000379: Replaced TV conditions 0.0000112: Processed additional conditions 0.0001390: Added where condition: class_key=msProduct, msProduct.id:!==132, msProduct.parent=43, msProduct.published=1, msProduct.deleted=0, OR:Data.made_in:==Краснодарский край, OR:Data.price:==8000000 0.0000031: Replaced TV conditions 0.0000291: Sorted by msProduct.id, ASC 0.0000021: Limited to 2, offset 0 0.0003200: SQL prepared «SELECT `msProduct`.`id`, `msProduct`.`type`, `msProduct`.`contentType`, `msProduct`.`pagetitle`, `msProduct`.`longtitle`, `msProduct`.`description`, `msProduct`.`alias`, `msProduct`.`alias_visible`, `msProduct`.`link_attributes`, `msProduct`.`published`, `msProduct`.`pub_date`, `msProduct`.`unpub_date`, `msProduct`.`parent`, `msProduct`.`isfolder`, `msProduct`.`introtext`, `msProduct`.`richtext`, `msProduct`.`template`, `msProduct`.`menuindex`, `msProduct`.`searchable`, `msProduct`.`cacheable`, `msProduct`.`createdby`, `msProduct`.`createdon`, `msProduct`.`editedby`, `msProduct`.`editedon`, `msProduct`.`deleted`, `msProduct`.`deletedon`, `msProduct`.`deletedby`, `msProduct`.`publishedon`, `msProduct`.`publishedby`, `msProduct`.`menutitle`, `msProduct`.`donthit`, `msProduct`.`privateweb`, `msProduct`.`privatemgr`, `msProduct`.`content_dispo`, `msProduct`.`hidemenu`, `msProduct`.`class_key`, `msProduct`.`context_key`, `msProduct`.`content_type`, `msProduct`.`uri`, `msProduct`.`uri_override`, `msProduct`.`hide_children_in_tree`, `msProduct`.`show_in_tree`, `msProduct`.`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`, `Data`.`own_firm`, `Data`.`franchise_firm`, `Data`.`lump_sum`, `Data`.`royalty`, `Data`.`payback`, `Data`.`contact_person`, `Data`.`phone_number`, `Data`.`email_address`, `Data`.`promo`, `Data`.`place`, `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`, IFNULL(`TVabs_views`.`value`, '0') AS `abs_views`, IFNULL(`TVcatalog_images`.`value`, '') AS `catalog_images`, IFNULL(`TVlogo_franchise`.`value`, '') AS `logo_franchise`, IFNULL(`TVpriority`.`value`, '') AS `priority` FROM `fran_site_content` AS `msProduct` LEFT JOIN `fran_ms2_products` `Data` ON `msProduct`.`id` = `Data`.`id` LEFT JOIN `fran_ms2_vendors` `Vendor` ON Data.vendor=Vendor.id LEFT JOIN `fran_site_tmplvar_contentvalues` `TVabs_views` ON `TVabs_views`.`contentid` = `msProduct`.`id` AND `TVabs_views`.`tmplvarid` = 22 LEFT JOIN `fran_site_tmplvar_contentvalues` `TVcatalog_images` ON `TVcatalog_images`.`contentid` = `msProduct`.`id` AND `TVcatalog_images`.`tmplvarid` = 3 LEFT JOIN `fran_site_tmplvar_contentvalues` `TVlogo_franchise` ON `TVlogo_franchise`.`contentid` = `msProduct`.`id` AND `TVlogo_franchise`.`tmplvarid` = 2 LEFT JOIN `fran_site_tmplvar_contentvalues` `TVpriority` ON `TVpriority`.`contentid` = `msProduct`.`id` AND `TVpriority`.`tmplvarid` = 28 WHERE ( `msProduct`.`class_key` = 'msProduct' AND `msProduct`.`id` != 132 AND `msProduct`.`parent` = 43 AND `msProduct`.`published` = 1 AND `msProduct`.`deleted` = 0 OR `Data`.`made_in` = 'Краснодарский край' OR `Data`.`price` = '8000000' ) GROUP BY msProduct.id ORDER BY msProduct.id ASC LIMIT 2 „ 0.0015578: SQL executed 0.0000200: Rows fetched 0.0000269: Returning raw data 0.0004170: Checked the active modifiers 0.0003850: Created “modChunk» from file «core/templates/chunks/filters/filterResultRow.html» 0.0017560: Compiled Fenom chunk with name «modchunk/f274287bd999472fd03acafb38210b64» 0.0007071: Loaded «modSnippet» with name «pThumb» 0.0005200: Time to load products options 0.0099130: Total time 6 291 456: Memory usage

Проблема в том, что почему-то выводится товар и текущий товар, хотя текущий ресурс исключён (132). Кто скажет почему?
Артур
13 декабря 2020, 01:02
modx.pro
260
0
Поблагодарить автора Отправить деньги

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

Alexey
13 декабря 2020, 11:37
0
Привет! Может, так?

'msProduct.id:!=' => $_modx->resource.id
    Артур
    13 декабря 2020, 14:47
    0
    А что это меняет? Если у меня $id = $_modx->resource.id))) Я конечно проблему решил, но мне не нравится это решение. Я в чанке делаю проверку на id и тупо не показываю товар если его id совпадает с id текущего ресурса. Но меня интересует почему ресурс не исключается?
    Павел Романов
    13 декабря 2020, 15:09
    0
    Добавьте в вызов:
    'resources' => '-'~$_modx->resource.id,
      Артур
      13 декабря 2020, 15:19
      0
      Это не работает. В логе есть строчка AND `msProduct`.`id` NOT IN (132) но текущий ресурс не исключается.
        Павел Романов
        14 декабря 2020, 09:03
        0
        А из where уберите )
          Артур
          14 декабря 2020, 12:47
          0
          Отличная мысль, но изначально, до того как, всё так и было, отдельным параметром задавался родитель и отдельным исключался ресурс, но в итоге всё равно формируется where.
      Alexey
      13 декабря 2020, 16:50
      0
      Да, если в чанке вызова $id = $_modx->resource.id, то я погорячился))

      В логе по условию where получается, что если эта часть возвращает true

      OR `Data`.`made_in` = 'Краснодарский край' OR `Data`.`price` = '8000000'
      то левая от первого OR часть не имеет значения. А проверка по $id как раз в левой части
        Артур
        13 декабря 2020, 16:52
        0
        т.е. надо проверку поставить в конец?
          Артур
          13 декабря 2020, 17:44
          0
          Как только не переставлял не работает как надо(((
          Alexey
          13 декабря 2020, 18:36
          0
          Тут дело в приоритетах выполнения OR и AND.

          {set $where = '(`msProduct`.`id` != ' ~ $id ~ ' AND (`msProduct`.`class_key` = 'msProduct' AND `msProduct`.`parent` = ' ~ $parent ~ ' AND `msProduct`.`published` = 1 AND `msProduct`.`deleted` = 0 OR `Data`.`made_in` = ' ~ $madeIn ~ ' OR `Data`.`price` = ' ~ $price ~ '))'}
          
          {'msProducts' | snippet: [
              'includeTVs' => 'catalog_images,logo_franchise,abs_views,priority',
              'limit' => 2,
              'tpl' =>  '@FILE chunks/filters/filterResultRow.html',
              'where' => [
              	$where
          	],
              'showLog' => 1
          ]}

          Вот такой вариант должен сработать, если ничего не упустил… наверно, можно как-то добавить приоритетные скобки в запрос where, который перебирает массив, но я сходу не увидел.
            Артур
            13 декабря 2020, 19:48
            0
            Скорее всего дело действительно в приоритете, но такая запись как у вас вообще не работает, но такой вызов
            {'msProducts' | snippet: [
                            'includeTVs' => 'catalog_images,logo_franchise,abs_views,priority',
                            'limit' => 2,
                            'tpl' =>  '@FILE chunks/filters/filterResultRow.html',
                            'showLog' => 1,
                            'where' => [
                                        'msProduct.parent' => $parent,
                                        'msProduct.id:!=' => $id,
                                        'msProduct.published' => 1,
                                        'msProduct.deleted' => 0,
                                        'OR:Data.made_in:=' => $madeIn,
                                        'OR:Data.price:=' => $price
                                        ]
                        ]}
            Дает такой вот лог
            <pre class="msProductsLog">0.0000539: pdoTools loaded. 0.0001791: Conditions prepared 0.0000229: xPDO query object created 0.0003340: Included list of tvs: <b>abs_views, catalog_images, logo_franchise, priority</b> 0.0001149: leftJoined <i>msProductData</i> as <b>Data</b> 0.0000739: leftJoined <i>msVendor</i> as <b>Vendor</b> 0.0000710: leftJoined <i>modTemplateVarResource</i> as <b>TVabs_views</b> 0.0000689: leftJoined <i>modTemplateVarResource</i> as <b>TVcatalog_images</b> 0.0000689: leftJoined <i>modTemplateVarResource</i> as <b>TVlogo_franchise</b> 0.0000679: leftJoined <i>modTemplateVarResource</i> as <b>TVpriority</b> 0.0000010: Grouped by <b>msProduct.id</b> 0.0001211: Added selection of <b>msProduct</b>: <small>`id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `alias_visible`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `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`</small> 0.0000570: Added selection of <b>msProductData</b>: <small>`article`, `price`, `old_price`, `weight`, `image`, `thumb`, `vendor`, `made_in`, `new`, `popular`, `favorite`, `tags`, `color`, `size`, `source`, `own_firm`, `franchise_firm`, `lump_sum`, `royalty`, `payback`, `contact_person`, `phone_number`, `email_address`, `promo`, `place`</small> 0.0000482: Added selection of <b>msVendor</b>: <small>`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`</small> 0.0000069: Added selection of <b>modTemplateVarResource</b>: <small>IFNULL(`value`, '0') AS `abs_views`</small> 0.0000060: Added selection of <b>modTemplateVarResource</b>: <small>IFNULL(`value`, '') AS `catalog_images`</small> 0.0000041: Added selection of <b>modTemplateVarResource</b>: <small>IFNULL(`value`, '') AS `logo_franchise`</small> 0.0000050: Added selection of <b>modTemplateVarResource</b>: <small>IFNULL(`value`, '') AS `priority`</small> 0.0000632: Replaced TV conditions 0.0000319: Processed additional conditions 0.0002871: Added where condition: <b>class_key=msProduct, msProduct.parent=43, msProduct.id:!==132, msProduct.published=1, msProduct.deleted=0, OR:Data.made_in:==Краснодарский край, OR:Data.price:==8000000</b> 0.0000029: Replaced TV conditions 0.0000391: Sorted by <b>msProduct.id</b>, <b>ASC</b> 0.0000010: Limited to <b>2</b>, offset <b>0</b> 0.0005159: SQL prepared <small>"SELECT `msProduct`.`id`, `msProduct`.`type`, `msProduct`.`contentType`, `msProduct`.`pagetitle`, `msProduct`.`longtitle`, `msProduct`.`description`, `msProduct`.`alias`, `msProduct`.`alias_visible`, `msProduct`.`link_attributes`, `msProduct`.`published`, `msProduct`.`pub_date`, `msProduct`.`unpub_date`, `msProduct`.`parent`, `msProduct`.`isfolder`, `msProduct`.`introtext`, `msProduct`.`richtext`, `msProduct`.`template`, `msProduct`.`menuindex`, `msProduct`.`searchable`, `msProduct`.`cacheable`, `msProduct`.`createdby`, `msProduct`.`createdon`, `msProduct`.`editedby`, `msProduct`.`editedon`, `msProduct`.`deleted`, `msProduct`.`deletedon`, `msProduct`.`deletedby`, `msProduct`.`publishedon`, `msProduct`.`publishedby`, `msProduct`.`menutitle`, `msProduct`.`donthit`, `msProduct`.`privateweb`, `msProduct`.`privatemgr`, `msProduct`.`content_dispo`, `msProduct`.`hidemenu`, `msProduct`.`class_key`, `msProduct`.`context_key`, `msProduct`.`content_type`, `msProduct`.`uri`, `msProduct`.`uri_override`, `msProduct`.`hide_children_in_tree`, `msProduct`.`show_in_tree`, `msProduct`.`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`, `Data`.`own_firm`, `Data`.`franchise_firm`, `Data`.`lump_sum`, `Data`.`royalty`, `Data`.`payback`, `Data`.`contact_person`, `Data`.`phone_number`, `Data`.`email_address`, `Data`.`promo`, `Data`.`place`, `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`, IFNULL(`TVabs_views`.`value`, '0') AS `abs_views`, IFNULL(`TVcatalog_images`.`value`, '') AS `catalog_images`, IFNULL(`TVlogo_franchise`.`value`, '') AS `logo_franchise`, IFNULL(`TVpriority`.`value`, '') AS `priority` FROM `fran_site_content` AS `msProduct` LEFT JOIN `fran_ms2_products` `Data` ON `msProduct`.`id` = `Data`.`id` LEFT JOIN `fran_ms2_vendors` `Vendor` ON Data.vendor=Vendor.id LEFT JOIN `fran_site_tmplvar_contentvalues` `TVabs_views` ON `TVabs_views`.`contentid` = `msProduct`.`id` AND `TVabs_views`.`tmplvarid` = 22 LEFT JOIN `fran_site_tmplvar_contentvalues` `TVcatalog_images` ON `TVcatalog_images`.`contentid` = `msProduct`.`id` AND `TVcatalog_images`.`tmplvarid` = 3 LEFT JOIN `fran_site_tmplvar_contentvalues` `TVlogo_franchise` ON `TVlogo_franchise`.`contentid` = `msProduct`.`id` AND `TVlogo_franchise`.`tmplvarid` = 2 LEFT JOIN `fran_site_tmplvar_contentvalues` `TVpriority` ON `TVpriority`.`contentid` = `msProduct`.`id` AND `TVpriority`.`tmplvarid` = 28 WHERE ( `msProduct`.`class_key` = 'msProduct' AND `msProduct`.`parent` = 43 AND `msProduct`.`id` != 132 AND `msProduct`.`published` = 1 AND `msProduct`.`deleted` = 0 OR `Data`.`made_in` = 'Краснодарский край' OR `Data`.`price` = '8000000' ) GROUP BY msProduct.id ORDER BY msProduct.id ASC LIMIT 2 "</small> 0.0024779: SQL executed 0.0000238: Rows fetched 0.0000370: Returning raw data 0.0006521: Checked the active modifiers 0.0005829: Created "modChunk" from file "core/templates/chunks/filters/filterResultRow.html" 0.0027871: Compiled Fenom chunk with name "modchunk/f274287bd999472fd03acafb38210b64" 0.0009439: Loaded "modSnippet" with name "pThumb" 0.0007551: Time to load products options 0.0148249: <b>Total time</b> 6 291 456: <b>Memory usage</b> </pre>
            Но в результате ресурс на странице которого происходит вызов не исключается из выборки.
              Alexey
              13 декабря 2020, 21:38
              0
              Не работает это как? Белый экран? Я проверил вариант из своего последнего коммента, есесно, немного попроще, на обычных ресурсах, sql- запрос строился верно в логе, все скобки норм расставились.

              В вашем случае не могу ничего сказать, нужно дебажить по факту.

              UPD: Кстати, только сейчас заметил, что тут

              class_key` = 'msProduct'
              нужно кавычки одиночные заэкранировать. Возможно, из-за этого феном все ломает.
                Артур
                13 декабря 2020, 22:20
                0
                Хорошо попробую. Спасибо
            Тодор
            14 декабря 2020, 15:45
            +1
            Выводитьса текущий ресурс потому что у вас так условие WHERE прописано,
            class_key=msProduct, 
            msProduct.id:!==132, 
            msProduct.parent=43, 
            msProduct.published=1, 
            msProduct.deleted=0,
            ИЛИ
            OR:Data.made_in:==Краснодарский край,
            ИЛИ
            OR:Data.price:==8000000
            и 132 ресурс подпадает под условие OR:Data.made_in:==Краснодарский край,
            Надо поиграть с WHERE, чтото типа:
            {'msProducts' | snippet:[
                'includeTVs' => 'catalog_images,logo_franchise,abs_views,priority',
                'limit' => 2,
                'tpl' =>  '@FILE chunks/filters/filterResultRow.html',
                'showLog' => 1,
                'where' => [
                    [
                        'msProduct.id:!=' => $id,
                        'msProduct.parent' => $parent,
                        'msProduct.published' => 1,
                        'msProduct.deleted' => 0
                    ],[
                        'Data.made_in:=' => $made_in, 
                        'OR:Data.price:=' => $price, 
                    ]
                ]
            ]}
            еще думаю надо будет поиграть с условием по цене, потому что в базе записиваються цена типа «8000000.00» а вы ищите «8000000», но ето не точно)))
              Артур
              14 декабря 2020, 17:43
              0
              Ну цель достигнута, но выглядит странно
              {'msProducts' | snippet: [
                          'includeTVs' => 'catalog_images,logo_franchise,abs_views,priority',
                          'limit' => 2,
                          'tpl' =>  '@FILE chunks/filters/filterResultRow.html',
                          'showLog' => 1,
                          'where' =>[
                              [
                              'msProduct.id:!=' => $id,
                              'msProduct.parent' => $parent,
                              'msProduct.published' => 1,
                              'msProduct.deleted' => 0,
                              'Data.price:>' => 0,
                              ],[
                              'OR:Data.made_in:=' => $made_in,
                              'msProduct.id:!=' => $id,
                              'msProduct.parent' => $parent,
                              ],[
                              'OR:Data.price:=' => $price,
                              'msProduct.id:!=' => $id,
                              'msProduct.parent' => $parent,
                              ]
                          ]
                          ]}
              Такой вариант выводит либо товары с такой же ценой, либо товары с тем же made_in, либо товары с таким же родителем.
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              15