Материал для экспертов.
Честно сказать, мало представляю, что это кому-то всерьез понадобится, но тем не менее опишу, хотя и сложно будет (несколько растянутая предыстория будет).
Если вы уже работали с нашими getdata-процессорами, понять тему публикации будет легче. Если нет, советую к прочтению: https://modxclub.ru/topics/vse-chto-vyi-xoteli-znat-o-proczessorax-no-boyalis-sprosit-1563.html
Итак, есть у нас getdata-процессор на получение товаров. При чем важно учитывать, что процессоры изначально расширяют другие процессоры на выборки, и рассчитаны на то, что их могут и далее расширять. В итоге один и тот же метод (как тот же prepareQueryBeforeCount, который нас здесь больше всего и интересует) может быть переопределен несколько раз, а конечный SQL-запрос сформироваться из нескольких дополняющих друг друга условий. Для лучшего понимания приведу небольшой пример на чистом xPDO. Сформируем простейший запрос на выборку документов.
На выходе получим SQL-запрос:
Теперь возьмем и добавим в него пару условий.
Результирующий запрос:
Теперь мы получим документы из раздела 85 и не удаленные.
Добавим еще условие, чтобы получить плюс к этому только опубликованные документы.
Да, xPDO позволяет несколько раз вызывать методы типа where, select, sortby и т.п.
Получили более сложный запрос:
Здесь, как мы видим, все условия перечислены через AND, так что скобки для нас не играют никакой роли. Но в случае, если у нас в запросе начинают фигурировать условия OR, картина сильно меняется, и очередность скобок и условий начинает играть очень важную роль. Вот давайте в запрос добавим условие "или раздел = 100". То есть у нас выборка уже идет из раздела 85, а хотим еще с теми же условиями выбрать, но включая раздел 100. Запрос расширим, следуя нашей текущей методике, то есть последовательно.
Что мы получим на выходе?
Вот тут уже запрос получился не такой, какой бы мы хотели. Здесь получилось буквально "Получить все документы (из раздела 85, не удаленные) и (опубликованные или из раздела 100)". А хотели бы "Получить все документы ((из раздела 85 или из раздела 100), не удаленные) и (опубликованные)". То есть наш желаемый запрос должен выглядеть примерно так:
Да, я знаю, что для таких целей можно было бы использовать конструкцию "parent:in" => array(85, 100), но мы рассматриваем не ту задачу, когда мы за один раз формируем нужный нам запрос, а случай, когда мы работаем уже с ранее подготовленным запросом и дальше добавляем в него свои условия.
Итак, прежде чем выдать окончательный вариант, давайте чуть перепишем наш запрос другим позволительным способом:
Это все то же самое, и SQL-запрос конечный тот же самый, но все условия мы не стали по частям отправлять в xPDO, а сначала подготовили массив условий. И здесь вот что интересно: xPDO вполне прилично справляется с многоуровневыми массивами запросов. К примеру, все то же самое можно запихнуть вот в такой массив:
На выходе сейчас мы получим ровно такой же SQL-запрос, что и ранее, то есть ничего не поменялось. Но теперь мы сформируем конечный правильный запрос и посмотрим что это нам дает.
Я специально добавил здесь больше условий, чтобы показать, что используя такой метод, можно добавлять свои условия в различные части запроса, не особо беспокоясь об очередности. Вот такой запрос у нас получился:
То есть, буквально, у нас получился запрос "Получить все документы (не удаленные и опубликованные) и (не скрытые в меню и у которых шаблон 1 или 2) и (раздел 85 или раздел 100)".
Что для нас важно здесь, это то, что условия, добавленные в первый элемент массива условий, будут распространяться на все условия второго элемента массива. То есть если мы хотим добавить еще несколько разделов, и при этом добавить условие поиска по заголовку, и еще добавить разделы, это можно сделать в любой последовательности. К примеру
Запрос:
На самом деле редки случаи построения таких хитрых запросов на лету, но тем не менее.
Так же уточню, что эти же условия-массивы можно отправлять и в pdoTools, и они должны работать с большой долей вероятности. Небольшой пример такого вызова: https://modx.pro/development/7236-pdofetch-search-in-tv-fields-with-the-delimiter/
UPD: Василий Наумкин подсказывает, что есть еще нативный способ подобное реализовывать через передачу группы запроса в orCondition()/andCondition().
Пример:
Но как мы совместно выяснили, это не дает полный контроль над формированием запроса. К примеру, этот код сформирует такой запрос:
То есть как я ни старался, он не сбил блоки условием OR, а только AND. А вот с использованием массивов получилось вот такой запрос сформировать:
получив вот такой запрос: