Простой массив в параметре filter метода getList() отлично подходит для условий, объединенных по логике «И» (AND). Но что делать, если нужна более сложная логика, например, (A AND B) OR C?
Для этого в D7 ORM существует мощный инструмент — объект \Bitrix\Main\ORM\Query\Filter\ConditionTree (дерево условий), который удобно создавать с помощью хелпера Query::filter().
Проблема простого массива
Рассмотрим задачу: найти все активные товары (ACTIVE = ‘Y’), у которых либо цена (PRICE) меньше 1000, либо количество (QUANTITY) равно 0.
Попытка собрать это в простом массиве будет выглядеть громоздко и неинтуитивно:
// Сложно и нечитаемо
'filter' => [
'=ACTIVE' => 'Y',
[
'LOGIC' => 'OR',
['<PRICE' => 1000],
['=QUANTITY' => 0]
]
]
Решение: Query::filter()
Класс Query предоставляет статический метод filter(), который возвращает пустой объект дерева условий. Этот объект имеет методы для построения сложной логики.
Основные методы ConditionTree:
- where($column, $operator, $value): Добавляет условие (аналог AND).
- whereIn($column, $values): Условие IN (…).
- whereNotIn(…), whereLike(…), whereBetween(…) и т.д.
- logic(‘or’ | ‘and’): Устанавливает, как будут объединяться следующие условия в текущей группе (OR или AND).
- addCondition(ConditionTree $condition): Добавляет вложенную группу условий.
Пример 1: Простая логика «ИЛИ» (OR)
Найдем элементы, у которых ID равен 10 ИЛИ символьный код равен ‘test’.
use Bitrix\Iblock\ElementTable;
use Bitrix\Main\ORM\Query\Query;
$result = ElementTable::getList([
'select' => ['ID', 'NAME', 'CODE'],
'filter' => Query::filter()
->logic('or') // Все следующие условия будут объединены через OR
->where('ID', 10)
->where('CODE', 'test')
]);
// SQL: ... WHERE `ID` = 10 OR `CODE` = 'test'
Пример 2: Комбинация «И» и «ИЛИ»
Вернемся к нашей задаче: активные товары, у которых (цена < 1000 ИЛИ количество = 0).
$result = \Bitrix\Catalog\ProductTable::getList([
'select' => ['ID', 'QUANTITY'],
'filter' => Query::filter()
->where('ACTIVE', 'Y') // Первое условие (AND)
->addCondition( // Добавляем вложенную группу условий
Query::filter()
->logic('or') // Внутри этой группы будет OR
->where('PRICE', '<', 1000)
->where('QUANTITY', '=', 0)
)
]);
// SQL: ... WHERE `ACTIVE` = 'Y' AND (`PRICE` < 1000 OR `QUANTITY` = 0)
Как это работает:
- Query::filter(): Создает основную группу условий (по умолчанию AND).
- ->where(‘ACTIVE’, ‘Y’): Добавляет первое условие в основную группу.
- ->addCondition(…): Добавляет новую, вложенную группу.
- Внутри addCondition мы создаем еще один объект Query::filter().
- ->logic(‘or’): Устанавливаем для вложенной группы логику «ИЛИ».
- ->where(…): Добавляем условия уже во вложенную группу.
Передача в getList
Готовый объект фильтра можно передавать в getList напрямую, вместо массива.
$myFilter = Query::filter()
->where('IBLOCK_ID', 5)
->where('ACTIVE', 'Y');
// ... какая-то логика ...
if ($someCondition) {
$myFilter->where('PROPERTY_X', 123);
}
$result = ElementTable::getList([
'select' => ['ID', 'NAME'],
'filter' => $myFilter // Передаем объект
]);
Вывод:
Использование Query::filter() — это ключ к написанию чистого, читаемого и гибкого кода для выборок данных.
Этот подход позволяет строить фильтры любой сложности, динамически добавляя условия, и делает ваш D7 ORM-код по-настоящему мощным.
D7 ORM, Query::filter, сложные фильтры, ORM ИЛИ, ORM AND, вложенные условия, ConditionTree, Bitrix ORM.