getList — центральный метод чтения данных в ORM Битрикс. Через его массив параметров описывается практически любой SELECT: поля, фильтры, сортировка, группировка и вычисляемые выражения.
Сигнатура и структура параметров
Метод getList() объявлен в DataManager и принимает один ассоциативный массив. Каждый ключ отвечает за часть SQL-запроса. Возвращается объект Bitrix\Main\ORM\Query\Result.
| Ключ | Назначение | Часть SQL |
|---|---|---|
select | список полей | SELECT |
filter | условия | WHERE |
order | сортировка | ORDER BY |
group | группировка | GROUP BY |
limit/offset | постраничность | LIMIT |
runtime | вычисляемые поля | выражения/JOIN |
count_total | общее число строк | отдельный COUNT |
Table::getList() вернёт все записи со всеми скалярными полями — на больших таблицах так делать нельзя, всегда указывайте select и limit.Выбор полей и алиасы
В select перечисляют имена полей из getMap(). Ключ массива задаёт алиас — под этим именем поле попадёт в результат.
$rows = OrderTable::getList([
'select' => [
'ID',
'SUM' => 'PRICE', // алиас
'USER_NAME' => 'USER.NAME', // поле через связь
],
'limit' => 50,
])->fetchAll();Через точку доступны поля связанных сущностей, если в карте описан referenceField. Символ * выбирает все скалярные поля текущей сущности, а USER.* — все поля связанной. Не увлекайтесь *: явный список полей и быстрее, и предсказуемее.
Фильтрация: операторы и IN
Ключи массива filter состоят из оператора-префикса и имени поля. Значение задаёт правую часть условия. Несколько ключей объединяются по AND.
'=ACTIVE' => 'Y'— точное равенство;'>PRICE' => 100— больше;'%NAME' => 'part'— LIKE с подстановкой;'!STATUS' => 'N'— не равно;'ID' => [1, 2, 3]— превращается в IN;'>— BETWEEN.[10, 90]
$result = ProductTable::getList([
'filter' => [
'=ACTIVE' => 'Y',
'>=PRICE' => 500,
'BRAND_ID' => [1, 5, 9],
'%NAME' => 'кабель',
],
]);
Сложная логика: ConditionTree и OR
Плоский массив фильтра объединяет условия только через AND. Для OR, вложенных групп и выражений применяют объект Bitrix\Main\ORM\Query\Filter\ConditionTree (удобно создавать через хелпер Query::filter()).
use Bitrix\Main\ORM\Query\Query;
$filter = Query::filter()
->logic('or')
->where('STATUS', 'N')
->where('STATUS', 'P');
$result = OrderTable::getList([
'filter' => [
$filter,
'>DATE_INSERT' => new \Bitrix\Main\Type\DateTime(),
],
]);Метод where() принимает поле, оператор и значение; whereIn(), whereNull(), whereLike() покрывают частые случаи. Деревья условий вкладываются друг в друга, что позволяет собрать произвольно сложный WHERE.
Сортировка, группировка и агрегаты
Сортировка задаётся массивом order вида «поле => направление». Группировка и агрегатные функции работают вместе с runtime-полями.
use Bitrix\Main\ORM\Fields\ExpressionField;
$stats = OrderTable::getList([
'select' => ['STATUS', 'CNT', 'TOTAL'],
'runtime' => [
new ExpressionField('CNT', 'COUNT(*)'),
new ExpressionField('TOTAL', 'SUM(%s)', ['PRICE']),
],
'group' => ['STATUS'],
'order' => ['CNT' => 'DESC'],
])->fetchAll();В ExpressionField плейсхолдер %s подставляет имя поля с корректным экранированием и алиасом таблицы. Это безопаснее конкатенации строк и работает с JOIN.
Постраничность и подсчёт
Для пагинации используют limit и offset. Чтобы узнать общее число записей без второго запроса вручную, есть флаг count_total.
$result = ProductTable::getList([
'select' => ['ID', 'NAME'],
'filter' => ['=ACTIVE' => 'Y'],
'limit' => 20,
'offset' => 40, // третья страница
'count_total' => true,
]);
$total = $result->getCount();
$rows = $result->fetchAll();Отладка и производительность
Главный риск ORM — незаметно сгенерировать тяжёлый SQL. Несколько приёмов держат выборки под контролем.
- получайте текст запроса:
$query = Table::query(); ... echo $query->getQuery();; - всегда ограничивайте
selectи добавляйтеlimit; - проверяйте, что поля фильтра и сортировки покрыты индексами;
- для повторяющихся выборок включайте кэш через
setCacheTtl(); - объектный режим (
fetchObject) не используйте на выборках в тысячи строк.
$query = ProductTable::query()
->setSelect(['ID', 'NAME'])
->where('ACTIVE', 'Y')
->setLimit(100)
->setCacheTtl(3600);
$rows = $query->fetchAll();
Итог
getList в D7 описывает SELECT через параметры select, filter, order, group, limit и runtime, а для сложной логики подключается ConditionTree и объект Query. Ключ к производительности — явный список полей, лимиты, индексы под фильтры и контроль сгенерированного SQL.
Мы в B2Bsite регулярно оптимизируем выборки на нагруженных каталогах и B2B-порталах: переписываем тяжёлые запросы, добавляем индексы и кэш. Если проект упирается в БД под ростом трафика — поможем разобрать узкие места и выдержать нагрузку.
Частые вопросы
Какие параметры принимает getList?
Один ассоциативный массив с ключами select, filter, order, group, limit, offset, runtime и count_total. Каждый отвечает за свою часть SQL-запроса.
Как задать условие OR в фильтре?
Плоский массив объединяет условия только по AND. Для OR используют объект ConditionTree через Query::filter() с методом logic('or') и цепочкой where.
Как выбрать поле связанной сущности?
Через точку в select, например 'USER.NAME', если в getMap описан referenceField USER. Так же можно фильтровать и сортировать по полям связи.
Как посчитать общее число записей?
Добавить в параметры count_total => true и вызвать getCount у результата. Учтите, что это отдельный COUNT-запрос, который лучше не выполнять на каждой странице.
Как сделать агрегат SUM или COUNT?
Объявить ExpressionField в runtime, добавить его алиас в select и указать group. Плейсхолдер %s в выражении безопасно подставляет имя поля.
Как увидеть сгенерированный SQL?
Собрать объект Query через Table::query() и вызвать getQuery. Это возвращает готовый текст запроса для профилирования.
Почему выборка тормозит?
Частые причины: отсутствие индексов под поля фильтра и сортировки, выборка всех полей через *, объектный режим на больших наборах и лишние count_total. Проверьте SQL и планы запросов.
Поможем с настройкой и поддержкой Для разработчиков
Поможем с настройкой, доработкой и поддержкой Для разработчиков.