ExpressionField — это мощный инструмент D7 ORM, который позволяет создавать «виртуальные» поля, значение которых вычисляется с помощью произвольного SQL-выражения.
Это позволяет перенести часть логики с PHP на сторону СУБД, что почти всегда значительно быстрее.
Когда использовать ExpressionField?
- Агрегатные функции: Когда нужно посчитать количество (COUNT), сумму (SUM), среднее (AVG) и т.д.
- Конкатенация полей: Когда нужно объединить несколько полей в одно (например, LAST_NAME и NAME).
- Вычисления с датами: Когда нужно рассчитать разницу между датами (DATEDIFF).
- Любые другие SQL-функции, специфичные для вашей СУБД.
Базовый синтаксис
ExpressionField создается и регистрируется «на лету» в runtime-параметре метода getList.
Конструктор: new ExpressionField(‘ALIAS’, ‘SQL_EXPRESSION’, [‘FIELD_1’, ‘FIELD_2’])
- ALIAS: Псевдоним для вашего нового поля (как AS в SQL).
- SQL_EXPRESSION: SQL-выражение с плейсхолдерами %s.
- [‘FIELD_1’, …]: Массив реальных полей сущности, которые будут подставлены вместо %s.
Пример 1: Подсчет количества (COUNT)
Задача: Получить список разделов инфоблока и для каждого посчитать количество активных элементов в нем.
use Bitrix\Main\Loader;
use Bitrix\Iblock\SectionTable;
use Bitrix\Main\Entity;
Loader::includeModule('iblock');
$result = SectionTable::getList([
'filter' => ['=IBLOCK_ID' => 5],
'select' => ['ID', 'NAME', 'ELEMENTS_COUNT'], // Выбираем наш новый алиас
'runtime' => [
// Связь с элементами (один-ко-многим)
new Entity\ReferenceField(
'ELEMENTS',
'\Bitrix\Iblock\ElementTable',
['=this.ID' => 'ref.IBLOCK_SECTION_ID', '=ref.ACTIVE' => new Entity\ExpressionField('', "'Y'")] // Доп. условие в JOIN
),
// Поле для подсчета
new Entity\ExpressionField(
'ELEMENTS_COUNT', // Алиас
'COUNT(%s)', // SQL-функция
['ELEMENTS.ID'] // Что считаем
)
]
]);
while ($row = $result->fetch()) {
echo "{$row['NAME']} (элементов: {$row['ELEMENTS_COUNT']}) <br>";
}
Пример 2: Конкатенация полей (CONCAT)
Задача: Получить список пользователей, выведя их полное имя в одном поле FULL_NAME.
use Bitrix\Main\UserTable;
use Bitrix\Main\Entity\ExpressionField;
$result = UserTable::getList([
'filter' => ['=ACTIVE' => 'Y'],
'select' => ['ID', 'LOGIN', 'FULL_NAME'],
'runtime' => [
new ExpressionField(
'FULL_NAME',
'CONCAT(%s, " ", %s)', // CONCAT для MySQL
['LAST_NAME', 'NAME']
)
]
]);
while ($row = $result->fetch()) {
echo "{$row['LOGIN']} - {$row['FULL_NAME']} <br>";
}
Пример 3: Вычисления с датами (DATEDIFF)
Задача: Найти, сколько дней прошло с момента регистрации каждого пользователя.
use Bitrix\Main\UserTable;
use Bitrix\Main\Entity\ExpressionField;
use Bitrix\Main\Application;
// Получаем SQL-хелпер для кросс-СУБД совместимости
$sqlHelper = Application::getConnection()->getSqlHelper();
$result = UserTable::getList([
'filter' => ['=ACTIVE' => 'Y'],
'select' => ['ID', 'LOGIN', 'DAYS_AGO'],
'runtime' => [
new ExpressionField(
'DAYS_AGO',
$sqlHelper->getDaysToDateFunction('%s'), // Используем хелпер
['DATE_REGISTER']
)
]
]);
Использование $sqlHelper (DATEDIFF для MySQL, другие функции для MSSQL/Oracle) делает ваш код совместимым с разными базами данных.
Вывод:
ExpressionField — это ключ к оптимизации сложных выборок. Вместо того чтобы получать «сырые» данные и обрабатывать их в PHP-цикле, вы заставляете базу данных делать эту работу за вас.
Это сокращает объем передаваемых данных, уменьшает нагрузку на PHP и делает ваши компоненты и скрипты значительно быстрее.
ExpressionField, D7 ORM, SQL функции, COUNT, CONCAT, DATEDIFF, runtime, агрегатные функции, Bitrix ORM, производительность.