Блог Горошко Андрея 1C-Битрикс ExpressionField в D7 ORM: SQL-функции и вычисления прямо в запросах

ExpressionField в D7 ORM: SQL-функции и вычисления прямо в запросах

Средний рейтинг
Еще нет оценок

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, производительность.

Мой рейтинг:

Добавить комментарий

Related Post

Современный Frontend в Битрикс: Система JS-расширений и CJSCore::InitСовременный Frontend в Битрикс: Система JS-расширений и CJSCore::Init

Средний рейтинг 5 из 5 звезд. 1 голосов. Времена хаотичного подключения <script> и <link> тегов в header.php прошли. Современный Битрикс предлагает мощную систему управления frontend-зависимостями — JS-расширения (extensions). Что такое расширение?Это именованный пакет, который может содержать: Зачем

Обновление количества товара на складе в BitrixОбновление количества товара на складе в Bitrix

Средний рейтинг Еще нет оценок Обновление количества товара на складе в Bitrix можно сделать так В коде ниже происходит следующее: Мой рейтинг:

Компонент main.ui.grid: Создание современной таблицы данных в БитриксКомпонент main.ui.grid: Создание современной таблицы данных в Битрикс

Средний рейтинг Еще нет оценок Старые таблицы (CAdminList) работают только в админке. Для публичной части (и современных админок) Битрикс предлагает компонент bitrix:main.ui.grid. Это мощный JS-грид с поддержкой сортировки, перетаскивания колонок,