MODX. &where, примеры записей условий для выборки (примеры предикатов)

В случае, если надо конкретизировать условия выборки записей, используются предикаты — выражения которые в качестве результата возвращают TRUE, FALSE или UNKNOWN. В случае использования CMF MODX количество вариаций записи предикатов возрастает, из-за большого количества языков, которые понимает данная система.

Различия записей в языках:

SQL: WHERE width = 15

MODX: &where=`width = 15`

JSON в тегах MODX: &where = `{ "width":15 }` (данный тип записи в тегах MODX может срабатывать но заносить ошибку в лог)

xPDO: $query->where(array('width' => 15));

JSON в fenom: 'where' => '{"width":15}' 

fenom: 'where' => [ 'width' => 15]

Ссылка на официальную документацию

Множественный выбор с условиями

MODX: &where=`width = 15 OR width = 25`

xPDO: $query->where(array(array( 'width' => 15), array('OR:width:=' => 25)));

JSON: { "0": { "width :=":"15","AND:height:=":"10" },"OR:width :=":"25" }

fenom: 'where' => [ 'width' => 15, 'OR:width:=' => 25 ]

Доступные операторы

  Символ Пример xPDO Пример MODX
Равно   'width' => 15 `width = 15`
= 'width:=' => 15  
Равно (безопасное сравнение значения NULL) <=>    
Не равно != 'width:!=' => 15 `width != 15`
<>    
Меньше > 'width:>' => 15 `width > 15`
Больше < 'width:<' => 15 `width < 15`
Больше или равно >= 'width:>=' => 15 `width >= 15`
Меньше или равно <= 'width:<=' => 15 `width <= 15`
Содержит LIKE

'width:LIKE' => '%15%'

Переменная в Fenom:

'width:LIKE' => '%'~$.get.tag~'%'

`width  LIKE %15%`
Не содержит NOT LIKE 'width:NOT LIKE' => '%15%' `width  NOT LIKE %15%`
В массиве IN 'width:IN' => array(15,16,17,20)  
Не в массиве NOT IN 'width:NOT IN' => array(15,16,17,20)  
  NOT   `width NOT 15 `
Если Null IS  'width:IS' => null `width IS null`
IS NULL   `width IS NULL `
Если Not Null IS NOT NULL   `width IS NOT NULL`
Между BETWEEN     
Включает EXISTS     
Не включает NOT EXISTS    
Соединяется COALESCE    
Интервал INTERVAL    
Наибольшее GREATEST    
Наименьшее LEAST    
Совпадает MATCH    
Максимум MAX    
Минимум MIN    
В среднем AVG    
Или OR

array( 'width' => 15), 

array('OR:width:=' => 10)

 
И AND

array( 'width' => 15), 

array('AND:height:=' => 10)

 
Регулярное выражение REGEXP   `pagetitle REGEXP "MODX"`

Трафаретные символы

При составлении предикатов (условий выборки) можно использовать трафаретные символы:

  • символ подчеркивания (_) — означает любой единичный символ в проверяемом значении;
  • символ процента (%) — означает последовательность любых символов в проверяемом значении. Количество символов в такой последовательности не ограничено (от 0 и более).
Образец Описание
'abc%' Любые строки, которые начинаются с букв «abc»
'abc_' Строки длиной строго 4 символа, причем первыми символами строки должны быть «abc»
'%z' Любая последовательность символов, которая обязательно заканчивается символом «z»
'%word%' Любая последовательность символов, содержащая слово «word» в любой позиции строки
'% % %' Текст, содержащий не менее 2-х пробелов, например, "World Wide Web"

Трафаретные символы открывают большой простор для творчества при создании предикатов:

# Где class не заканчивается на o, но не на go
WHERE class NOT LIKE '%go' AND class LIKE '%o' ;

С трафаретными символами может возникнуть проблема в случае если искомая строка будет содержать аналогичные символы, например, если надо отыскать все значения, содержащие символ «_», то шаблон ‘%_%’ приведет к тому, что будут возвращены все записи из таблицы. В этом случае поможет указание экранирующего символа в ESCAPE или экранирующий символ \.

# указываем что символ # является экранирующим
'%#_%' ESCAPE '#'

# назначить можно любой символ, в этом примере | 
LIKE '25|%' ESCAPE '|'

# некоторые версии SQL в качестве экранирующего могут принимать обратный слеш (\),
# по примеру популярных языков программирования
'%\_%'
'25\%'

 

Теги MODX

[[pdoResources? 
     &where = `published=1,deleted=0,createdby=12`
     ...
]]

Для сложных конструкций можно использовать чанк, сниппет или плейсхолдер вместо строки:

[[pdoResources? 
     &where=`[[CalculatedWhere]]` 
     ...
]]

пример такого сниппета:

$where = array(
    'published' => 1,
    'deleted' => 0,
    'createdby' => $modx->user->get('id'),
);
return $modx->toJSON($where);

Json

Обратите внимание, что при использовании JSON записи одновременно с шаблонизатором Fenom, после фигурных скобок надо проставлять пробелы. Иначе запись может вызвать ошибку в логах, несмотря на то что код будет обработан правильно.

[[pdoResources? 
     &where = `{ "published":1,"deleted":0,"createdby":12 }`
     ...
]]

Использование плейсхолдеров

Плейсхолдеры должны формироваться до вызова ресурсов. К примеру сниппет SetWhere формирующий плейсхолдер:

$jsonString = $modx->toJSON($input);
$modx->setPlaceholder('CalculatedWhere', $jsonString);

Вызов сниппетов

[[SetWhere? 
   &input=`month=January,year=2015`
]]

[[pdoResources? 
   &where=`[[+CalculatedWhere]]` 
   ...
]]

Несколько вызовов на странице можно сформировать добавив дополнительный параметр. Формирование плейсхолдера:

$placeholderName = $scriptProperties['ph']
// ...
 
$modx->setPlaceholder($placeholderName, $value);

Вызов на странице:

[[SetWhere? 
   $month=`January` 
   &year=`2015 
   &ph=`January`
]]

[[getResources? 
   &where=`[[+January]]` 
   ...
]]
 
...
 
[[SetWhere? 
   $month=`February` 
   &year=`2015 
   &ph=`February`
]]

[[getResources? 
   &where=`[[+February]]`
   ...
]]

Примеры

Получение всех ресурсов, опубликованных в течение определенного месяца того или иного года

[[getResources? 
    &where=`[[CalculatedWhere? &month=`January` &year=`2015`]]`
    ...
]]

Сниппет CalculatedWhere

$month = $scriptProperties['month'];
$year = $scriptProperties['year'];
$a_date = $month . ' ' . $year;
$min = strtotime($a_date);
$time = date("Y-m-t 23:59", $min);
$max =  strtotime($time);
 
$where = array(
    'publishedon:>=' => $min,
    'publishedon:<=' => $max,
);
 
return $modx->toJSON($where);


// будет сформирована JSON строка вида 
// {"publishedon:>=":1420092000,"publishedon:<=":1422770340}

Данные какого-либо плейсхолдера входят в массив

[[pdoResources? 
    &where = `[[+id]] IN (1,2,3,4,5)`
    ...
]]

php конструкция, формирующая запрос where

// опубликованные ресурсы, не являющиеся каталогом
$where = array( 'published' => 1, 'isfolder' => 0, );

// формирование were из GET данных
$filter = array();

if($_GET['tags']) {
 $filter[] = 'tags='.$_GET['tags'];
}

if($filter) {
 $where = $modx->toJSON(array($filter));
} else {
 $where = '';
}

$params = array(
 ...
 'where' => $where
);

where и оператор like в php

$arr = array (5,15,10,20);

$params = array(
...
'where' => [ 
              'field:LIKE' => '%'.$arr.'%',
              'field2:LIKE' => $arr.'%',
              'field3:LIKE' => '%'.$arr
           ],
...
);

$out = $modx->runSnippet('pdoPage', $params);

Возможные ошибки

  • Если после составления условия where в логах возникает ошибка «Error parsing condition with key 0», то вероятно неправильно составлены критерии выборки. Например, отсутствует хотя бы 1 рабочий параметр: «pagetitle REGEXP "MODX"» выдаст ошибку, в то время как «isfolder = 0 and pagetitle REGEXP "MODX"» выведет искомый результат.