Полный цикл в digital

Построитель запросов ORM

Методы выборки getList сразу выполняют запросы и возвращают результаты. Они подходят для простых запросов, но неудобны если параметры неизвестны заранее или нужна сложная логика.

Гибкость с Bitrix\Main\Entity\Query. Для гибкой настройки запросов используйте объект Bitrix\Main\Entity\Query. Он накапливает параметры для запроса. Это полезно, когда параметры неизвестны заранее и формируются программно.

Пример с getList:

$result = BookTable::getList([
    'select' => ['ISBN', 'TITLE', 'PUBLISH_DATE'],
    'filter' => ['=ID' => 1]
]);

Аналогичный пример с Bitrix\Main\Entity\Query:

$q = new Bitrix\Main\Entity\Query(BookTable::getEntity());
$q->setSelect(['ISBN', 'TITLE', 'PUBLISH_DATE']);
$q->setFilter(['=ID' => 1]);
$result = $q->exec();

Объект Bitrix\Main\Entity\Query ключевой элемент для выборки данных и используется внутри getList. Однако переопределение методов getList может быть ограничено, метод может сработать при вызове, но не через Bitrix\Main\Entity\Query.

Постепенное добавление параметров

Если вы не знаете заранее, какие поля выбрать или какие фильтры применить, используйте объект Bitrix\Main\Entity\Query для постепенного добавления параметров.

$query = new Bitrix\Main\Entity\Query(BookTable::getEntity());
attachSelect($query);
attachOthers($query);
$result = $query->exec();

// Функция для добавления полей в запрос
function attachSelect(Bitrix\Main\Entity\Query $query): void
{
    $query->addSelect('ID');

    // Условие для добавления поля ISBN
    if (/* условие */) {
        $query->addSelect('ISBN');
    }
}

function attachOthers(Bitrix\Main\Entity\Query $query): void
{
    // Условие для добавления фильтра
    if (/* условие */) {
        $query->setFilter(/* параметры фильтра */);
    }

    // Условие для добавления сортировки
    if (/* условие */) {
        $query->setOrder(/* параметры сортировки */);
    }
}

Создание объекта Query

Используем new Bitrix\Main\Entity\Query(BookTable::getEntity()) для создания нового объекта Query, связанного с сущностью BookTable. Это будет основой для построения запроса.

Добавление полей в запрос

Функция attachSelect добавляет поля, которые нужно выбрать из базы данных.

  1. addSelect('ID') добавляет поле ID в список выбираемых полей
  2. Условие внутри функции добавляет поле ISBN, если оно необходимо

Добавление фильтров и сортировки

Функция attachOthers добавляет фильтры и сортировку.

  1. setFilter устанавливает условия фильтрации данных
  2. setOrder задает порядок сортировки результатов

Запрос без выполнения

Объект Bitrix\Main\Entity\Query позволяет строить запрос без его выполнения. Это полезно для подзапросов или получения текста запроса:

$q = new Bitrix\Main\Entity\Query(BookTable::getEntity());
$q->setSelect(['ID']);
$q->setFilter(['=PUBLISH_DATE' => new Type\Date('2014-12-13', 'Y-m-d')]);
$sql = $q->getQuery();
file_put_contents('/tmp/today_books.sql', $sql);
// Запрос "SELECT ID FROM my_book WHERE PUBLISH_DATE='2014-12-31'" будет сохранен в файл, но не выполнен.

Доступные методы

Список методов Bitrix\Main\Entity\Query:

Получение данных

  • setSelect(), setGroup() устанавливает массив с именами полей
  • addSelect(), addGroup() добавляет имя поля
  • getSelect(), getGroup() возвращает массив с именами полей

Фильтрация данных

  • setFilter() устанавливает одно или многомерный массив с описанием фильтра
  • addFilter() добавляет один параметр фильтра со значением
  • getFilter() возвращает текущее описание фильтра

Сортировка данных

  • setOrder() устанавливает массив с именами полей и порядком сортировки
  • addOrder() добавляет одно поле с порядком сортировки
  • getOrder() возвращает текущее описание сортировки

Ограничение количества данных

  • setLimit(), setOffset() устанавливает значение
  • getLimit(), getOffset() возвращает текущее значение

Временное поле

  • registerRuntimeField() регистрирует новое временное поле для исходной сущности

С какими сущностями работает построитель запросов

Всё что написано ниже, применимо и к другим модулям, только названия таблиц будут другие. Многое можно узнать из файла /bitrix/modules/main/lib/orm/data/datamanager.php

Подключаем модуль:

\Bitrix\Main\Loader::includeModule('iblock');

После подключения модуля, нам становится доступен целый набор различных классов и методов для работы с данными инфоблоков. Существуют и другие методы для работы с инфоблоками, и это лишь часть из них. Наиболее часто используемые методы, это получение списков записей:

  1. \Bitrix\Iblock\TypeTable::getEntity(); типы инфоблоков
  2. \Bitrix\Iblock\IblockTable::getEntity(); инфоблоки
  3. \Bitrix\Iblock\PropertyTable::getEntity(); свойства инфоблоков
  4. \Bitrix\Iblock\PropertyEnumerationTable::getEntity(); значения свойств, например списков
  5. \Bitrix\Iblock\SectionTable::getEntity(); разделы инфоблоков
  6. \Bitrix\Iblock\ElementTable::getEntity(); элементы инфоблоков
  7. \Bitrix\Iblock\InheritedPropertyTable::getEntity(); наследуемые свойства, seo шаблоны

Автоматическая генерация класса

Для использования генератора ORM классов перейдите на страницу Настройки -> Настройки продукта -> Настройки модулей -> Монитор производительности модуль Монитор производительности должен быть установлен. На вкладке Генератор таблетов отметьте поле Разрешить генерацию таблетов для ORM.

Автоматически сгенерировать класс с описанием любой таблицы можно на странице Настройки -> Производительность -> Таблицы, в меню действий доступен пункт ORM

Выборка

Выбираем элементы инфоблока с идентификатором 5:

Bitrix\Main\Loader::includeModule('iblock');
// создаем объект Query, в качестве параметра передаем объект сущности (элемент инфоблока)
$query = new Bitrix\Main\Entity\Query(
    Bitrix\Iblock\ElementTable::getEntity()
);
// выбираем идентификатор элемента, символьный код и наименование
$query->setSelect(array('ID', 'CODE', 'NAME'))
    // идентификатор инфоблока равен 5
    ->setFilter(array('IBLOCK_ID' => 5))
    // сортируем элементы по идентификатору, по возрастанию
    ->setOrder(array('ID' => 'ASC'))
    // выбираем только три элемента
    ->setLimit(3);
// посмотрим, какой запрос был сформирован
echo '<pre>' . $query->getQuery() . '</pre>';
// выполняем запрос
$result = $query->exec();
// выводим результат
while ($row = $result->fetch()) {
    pp($row);
}

Запрос:

SELECT
`iblock_element`.`ID` AS `ID`,
`iblock_element`.`CODE` AS `CODE`,
`iblock_element`.`NAME` AS `NAME`
FROM
`b_iblock_element` `iblock_element`
WHERE
`iblock_element`.`IBLOCK_ID` = 5
ORDER BY
`ID` ASC
LIMIT
0, 3

Ответ:

Array
(
    [ID] => 347
    [CODE] => angliyskiy-buldog
    [NAME] => Английский бульдог
)
Array
(
    [ID] => 348
    [CODE] => dalmatin
    [NAME] => Далматин
)
Array
(
    [ID] => 349
    [CODE] => afganskaya-borzaya
    [NAME] => Афганская борзая
)

Соединение

Например через сущность ElementTable, можно выбирать или ставить условия на поля связанной сущности, в данном примере это IBLOCK. Связанная таблица по умолчанию присоединяется с помощью LEFT JOIN. Вспомним reference поле IBLOCK в описании ElementTable:

'IBLOCK' => array(
'data_type' => 'Bitrix\Iblock\Iblock',
'reference' => array('=this.IBLOCK_ID' => 'ref.ID'),
)

Выберем данные самого инфоблока вместе с элементами инфоблока:

Bitrix\Main\Loader::includeModule('iblock');
// создаем объект Query, в качестве параметра передаем объект сущности (элемент инфоблока)
$query = new Bitrix\Main\Entity\Query(
    Bitrix\Iblock\ElementTable::getEntity()
);
// выборка
$query->setSelect(array('ID', 'CODE', 'NAME', 'IBLOCK.ID', 'IBLOCK.CODE', 'IBLOCK.NAME'))
    // за место этого
    // ->setFilter(array('IBLOCK_ID' => 5))
    // можно так
    ->setFilter(array('IBLOCK.ID' => 5))
    // сортировка
    ->setOrder(array('ID' => 'ASC'))
    // лимит
    ->setLimit(3);
// посмотрим, какой запрос был сформирован
echo '<pre>' . $query->getQuery() . '</pre>';
// выполняем запрос
$result = $query->exec();
// выводим результат
while ($row = $result->fetch()) {
    pp($row);
}

Запрос:

SELECT
`iblock_element`.`ID` AS `ID`,
`iblock_element`.`CODE` AS `CODE`,
`iblock_element`.`NAME` AS `NAME`,
`iblock_element_iblock`.`ID` AS `IBLOCK_ELEMENT_IBLOCK_ID`,
`iblock_element_iblock`.`CODE` AS `IBLOCK_ELEMENT_IBLOCK_CODE`,
`iblock_element_iblock`.`NAME` AS `IBLOCK_ELEMENT_IBLOCK_NAME`
FROM
`b_iblock_element` `iblock_element` LEFT JOIN `b_iblock` `iblock_element_iblock`
ON `iblock_element`.`IBLOCK_ID` = `iblock_element_iblock`.`ID`
WHERE
`iblock_element_iblock`.`ID` = 5
ORDER BY
`ID` ASC
LIMIT
0, 3

Ответ:

Array
(
    [ID] => 347
    [CODE] => angliyskiy-buldog
    [NAME] => Английский бульдог
    [IBLOCK_ELEMENT_IBLOCK_ID] => 5
    [IBLOCK_ELEMENT_IBLOCK_CODE] => articles
    [IBLOCK_ELEMENT_IBLOCK_NAME] => Статьи о домашних животных
)
Array
(
    [ID] => 348
    [CODE] => dalmatin
    [NAME] => Далматин
    [IBLOCK_ELEMENT_IBLOCK_ID] => 5
    [IBLOCK_ELEMENT_IBLOCK_CODE] => articles
    [IBLOCK_ELEMENT_IBLOCK_NAME] => Статьи о домашних животных
)
Array
(
    [ID] => 349
    [CODE] => afganskaya-borzaya
    [NAME] => Афганская борзая
    [IBLOCK_ELEMENT_IBLOCK_ID] => 5
    [IBLOCK_ELEMENT_IBLOCK_CODE] => articles
    [IBLOCK_ELEMENT_IBLOCK_NAME] => Статьи о домашних животных
)

Соединение со сложной логикой

В определении runtime-reference поля можно указывать тип соединения LEFT, RIGHT, INNER, в фильтре использовать сложную логику, как в CIblockElement::GetList():

Bitrix\Main\Loader::includeModule('iblock');
// создаем объект Query, в качестве параметра передаем объект сущности (инфоблок)
$query = new Bitrix\Main\Entity\Query(
    Bitrix\Iblock\IblockTable::getEntity()
);
// регистрируем новое временное поле для исходной сущности
$query->registerRuntimeField(
    // поле element как ссылка на таблицу b_iblock_element
    'element',
    array(
        // тип — сущность ElementTable
        'data_type' => 'Bitrix\Iblock\ElementTable',
        // this.ID относится к таблице, относительно которой строится запрос, т.е. b_iblock.ID = b_iblock_element.IBLOCK_ID
        'reference' => array('=this.ID' => 'ref.IBLOCK_ID'),
        // тип соединения INNER JOIN
        'join_type' => 'INNER'
    )
);
// регистрируем новое временное поле для исходной сущности
$query->registerRuntimeField(
    // поле type как ссылка на таблицу b_iblock_type
    'type',
    array(
        'data_type' => 'Bitrix\Iblock\TypeTable',
        'reference' => array('=this.IBLOCK_TYPE_ID' => 'ref.ID'),
        'join_type' => 'INNER'
    )
);
// выбираем название инфоблока, символьный код инфоблока, название элемента, символьный код элемента и идентификатор типа инфоблока
$query->setSelect(array('NAME', 'CODE', 'element.NAME', 'element.CODE', 'type.ID'));
// выбираем элементы с идентификаторами 348 или 349
$query->setFilter(
    array(
        'LOGIC' => 'OR',
        array('element.ID' => 348),
        array('element.ID' => 349),
    )
);
// посмотрим, какой запрос был сформирован
echo '<pre>' . $query->getQuery() . '</pre>';
// выполняем запрос
$result = $query->exec();
// выводим результат
while ($row = $result->fetch()) {
    pp($row);
}

Запрос:

SELECT
`iblock_iblock`.`NAME` AS `NAME`,
`iblock_iblock`.`CODE` AS `CODE`,
`iblock_iblock_element`.`NAME` AS `IBLOCK_IBLOCK_element_NAME`,
`iblock_iblock_element`.`CODE` AS `IBLOCK_IBLOCK_element_CODE`,
`iblock_iblock_type`.`ID` AS `IBLOCK_IBLOCK_type_ID`
FROM
`b_iblock` `iblock_iblock`
INNER JOIN `b_iblock_element` `iblock_iblock_element`
ON `iblock_iblock`.`ID` = `iblock_iblock_element`.`IBLOCK_ID`
INNER JOIN `b_iblock_type` `iblock_iblock_type`
ON `iblock_iblock`.`IBLOCK_TYPE_ID` = `iblock_iblock_type`.`ID`
WHERE
(`iblock_iblock_element`.`ID` = 348) OR (`iblock_iblock_element`.`ID` = 349)

Ответ:

Array
(
    [NAME] => Статьи о домашних животных
    [CODE] => articles
    [IBLOCK_IBLOCK_element_NAME] => Далматин
    [IBLOCK_IBLOCK_element_CODE] => dalmatin
    [IBLOCK_IBLOCK_type_ID] => content
)
Array
(
    [NAME] => Статьи о домашних животных
    [CODE] => articles
    [IBLOCK_IBLOCK_element_NAME] => Афганская борзая
    [IBLOCK_IBLOCK_element_CODE] => afganskaya-borzaya
    [IBLOCK_IBLOCK_type_ID] => content
)

Агрегатные функции

В запросах можно использовать агрегатные функции MySQL. Для это служит метод registerRuntimeField(), регистрирующий новое поле на время выполнения запроса. Посмотрим, сколько активных элементов в инфоблоке:

Bitrix\Main\Loader::includeModule('iblock');
// создаем объект Query, в качестве параметра передаем объект сущности (элемент инфоблока)
$query = new Bitrix\Main\Entity\Query(
    Bitrix\Iblock\ElementTable::getEntity()
);
// регистрируем новое временное поле для исходной сущности
$query->registerRuntimeField(
    'ACTIVE_ELEMENTS',
    array(
        // тип вычисляемого поля
        'data_type' => 'string',
        // агрегатная функция (COUNT, MAX, MIN, SUM, AVG) и поле для подстановки
        'expression' => array('GROUP_CONCAT(%s)', 'NAME')
    )
);
// выборка
$query->setSelect(array('IBLOCK.NAME', 'ACTIVE_ELEMENTS'));
// фильтр
$query->setFilter(array('IBLOCK.ID' => 5, '=ACTIVE' => 'Y'));
// посмотрим, какой запрос был сформирован
echo '<pre>' . $query->getQuery() . '</pre>';
// выполняем запрос
$result = $query->exec();
// выводим результат
while ($row = $result->fetch()) {
    pp($row);
}

Запрос:

SELECT
`iblock_element_iblock`.`NAME` AS `IBLOCK_ELEMENT_IBLOCK_NAME`,
GROUP_CONCAT(`iblock_element`.`NAME`) AS `ACTIVE_ELEMENTS`
FROM
`b_iblock_element` `iblock_element` LEFT JOIN `b_iblock` `iblock_element_iblock`
ON `iblock_element`.`IBLOCK_ID` = `iblock_element_iblock`.`ID`
WHERE
`iblock_element_iblock`.`ID` = 5 AND `iblock_element`.`ACTIVE` = 'Y'
GROUP BY
`iblock_element_iblock`.`NAME`

Ответ:

Array
(
    [IBLOCK_ELEMENT_IBLOCK_NAME] => Статьи о домашних животных
    [ACTIVE_ELEMENTS] => Английский бульдог,Далматин,Афганская борзая,Абиссинская кошка,Сиамская кошка,Американский бобтейл,Британская короткошерстная,Лабрадор,Лайка
)

Подсчет

Выбираем разделы инфоблока с идентифкатором 5 и подсчитываем количество элементов в каждом, учитываем только активные разделы и элементы:

Bitrix\Main\Loader::includeModule('iblock');
// создаем объект Query, в качестве параметра передаем объект сущности (элемент инфоблока)
$query = new Bitrix\Main\Entity\Query(
    Bitrix\Iblock\ElementTable::getEntity()
);
// регистрируем новое временное поле для исходной сущности
$query->registerRuntimeField(
    'ELEMENT_COUNT',
    array(
        // тип вычисляемого поля
        'data_type' => 'integer',
        // агрегатная функция (COUNT, MAX, MIN, SUM, AVG) и поле для подстановки
        'expression' => array('COUNT(%s)', 'NAME')
    )
);
// регистрируем новое временное поле для исходной сущности
$query->registerRuntimeField(
    'ELEMENT_LIST',
    array(
        // тип вычисляемого поля
        'data_type' => 'string',
        // агрегатная функция (COUNT, MAX, MIN, SUM, AVG) и поле для подстановки
        'expression' => array('GROUP_CONCAT(%s)', 'NAME')
    )
);
// выборка
$query->setSelect(array('IBLOCK_SECTION.NAME', 'ELEMENT_COUNT', 'ELEMENT_LIST'));
// учитываем только активные разделы и активные элементы
$query->setFilter(array('=ACTIVE' => 'Y', '=IBLOCK_SECTION.ACTIVE' => 'Y'));
// выбираем только разделы инфоблока с идентификатором 5
$query->addFilter('IBLOCK.ID', 5);
// посмотрим, какой запрос был сформирован
echo '<pre>' . $query->getQuery() . '</pre>';
// выполняем запрос
$result = $query->exec();
// выводим результат
while ($row = $result->fetch()) {
    pp($row);
}

Запрос:

SELECT
`iblock_element_iblock_section`.`NAME` AS `IBLOCK_ELEMENT_IBLOCK_SECTION_NAME`,
COUNT(`iblock_element`.`NAME`) AS `ELEMENT_COUNT`,
GROUP_CONCAT(`iblock_element`.`NAME`) AS `ELEMENT_LIST`
FROM
`b_iblock_element` `iblock_element`
LEFT JOIN `b_iblock_section` `iblock_element_iblock_section`
ON `iblock_element`.`IBLOCK_SECTION_ID` = `iblock_element_iblock_section`.`ID`
LEFT JOIN `b_iblock` `iblock_element_iblock`
ON `iblock_element`.`IBLOCK_ID` = `iblock_element_iblock`.`ID`
WHERE
`iblock_element`.`ACTIVE` = 'Y' AND
`iblock_element_iblock_section`.`ACTIVE` = 'Y' AND
`iblock_element_iblock`.`ID` = 5
GROUP BY
`iblock_element_iblock_section`.`NAME`

Ответ:

Array
(
    [IBLOCK_ELEMENT_IBLOCK_SECTION_NAME] => Породы кошек
    [ELEMENT_COUNT] => 4
    [ELEMENT_LIST] => Абиссинская кошка,Сиамская кошка,Американский бобтейл,Британская короткошерстная
)
Array
(
    [IBLOCK_ELEMENT_IBLOCK_SECTION_NAME] => Породы собак
    [ELEMENT_COUNT] => 3
    [ELEMENT_LIST] => Английский бульдог,Далматин,Афганская борзая
)
Array
(
    [IBLOCK_ELEMENT_IBLOCK_SECTION_NAME] => Служебные породы
    [ELEMENT_COUNT] => 2
    [ELEMENT_LIST] => Лабрадор,Лайка
)

Добавим еще одно условие, чтобы выбирать только разделы, содержащие более трех элементов:

$query->addFilter('>ELEMENT_COUNT', 3);

Запрос:

SELECT
`iblock_element_iblock_section`.`NAME` AS `IBLOCK_ELEMENT_IBLOCK_SECTION_NAME`,
COUNT(`iblock_element`.`NAME`) AS `ELEMENT_COUNT`,
GROUP_CONCAT(`iblock_element`.`NAME`) AS `ELEMENT_LIST`
FROM
`b_iblock_element` `iblock_element`
LEFT JOIN `b_iblock_section` `iblock_element_iblock_section`
ON `iblock_element`.`IBLOCK_SECTION_ID` = `iblock_element_iblock_section`.`ID`
LEFT JOIN `b_iblock` `iblock_element_iblock`
ON `iblock_element`.`IBLOCK_ID` = `iblock_element_iblock`.`ID`
WHERE
`iblock_element`.`ACTIVE` = 'Y' AND
`iblock_element_iblock_section`.`ACTIVE` = 'Y' AND
`iblock_element_iblock`.`ID` = 5
GROUP BY
`iblock_element_iblock_section`.`NAME`
HAVING
COUNT(`iblock_element`.`NAME`) > 3

Ответ:

Array
(
    [IBLOCK_ELEMENT_IBLOCK_SECTION_NAME] => Породы кошек
    [ELEMENT_COUNT] => 4
    [ELEMENT_LIST] => Абиссинская кошка,Сиамская кошка,Американский бобтейл,Британская короткошерстная
)

Ссылка на другую сущность

Runtime поле может быть не только вычисляемым значением, но и ссылкой на другую сущность. Т.е. в методе getMap() можно не описывать связь, а сформировать ее прямо в запросе. Например, создадим объект Query для сущности IblockTable, свяжем ее с ElementTable и выберем элемент с ID=349:

Bitrix\Main\Loader::includeModule('iblock');
// создаем объект Query, в качестве параметра передаем объект сущности (инфоблок)
$query = new Bitrix\Main\Entity\Query(
    Bitrix\Iblock\IblockTable::getEntity()
);
// регистрируем новое временное поле для исходной сущности
$query->registerRuntimeField(
    // поле element как ссылка на таблицу b_iblock_element
    'element',
    array(
        // тип — сущность ElementTable
        'data_type' => 'Bitrix\Iblock\ElementTable',
        // this.ID относится к таблице, относительно которой строится запрос, т.е. b_iblock.ID = b_iblock_element.IBLOCK_ID
        'reference' => array('=this.ID' => 'ref.IBLOCK_ID'),
    )
);
// выбираем название элемента, символьный код, краткое описание, кол-во просмотров и название инфоблока
$query->setSelect(array('element.NAME', 'element.CODE', 'element.PREVIEW_TEXT', 'element.SHOW_COUNTER',  'NAME'));
// выбираем только элемент с идентификатором 349
$query->setFilter(array('element.ID' => 349));
// посмотрим, какой запрос был сформирован
echo '<pre>' . $query->getQuery() . '</pre>';
// выполняем запрос
$result = $query->exec();
// выводим результат
while ($row = $result->fetch()) {
    pp($row);
}

Запрос:

SELECT
    `iblock_iblock_element`.`NAME` AS `IBLOCK_IBLOCK_element_NAME`,
    `iblock_iblock_element`.`CODE` AS `IBLOCK_IBLOCK_element_CODE`,
    `iblock_iblock_element`.`PREVIEW_TEXT` AS `IBLOCK_IBLOCK_element_PREVIEW_TEXT`,
    `iblock_iblock_element`.`SHOW_COUNTER` AS `IBLOCK_IBLOCK_element_SHOW_COUNTER`,
    `iblock_iblock`.`NAME` AS `NAME`
  FROM
    `b_iblock` `iblock_iblock` LEFT JOIN `b_iblock_element` `iblock_iblock_element`
    ON `iblock_iblock`.`ID` = `iblock_iblock_element`.`IBLOCK_ID`
  WHERE
    `iblock_iblock_element`.`ID` = 349

Ответ:

Array
(
    [IBLOCK_IBLOCK_element_NAME] => Афганская борзая
    [IBLOCK_IBLOCK_element_CODE] => afganskaya-borzaya
    [IBLOCK_IBLOCK_element_PREVIEW_TEXT] => Изящная красавица с длинной развевающейся на бегу шелковистой шерстью...
    [IBLOCK_IBLOCK_element_SHOW_COUNTER] => 10
    [NAME] => Статьи о домашних животных
)

Пользовательские свойства

Получаем пользовательские свойства элементов инфоблока с идентификатором 5:

Bitrix\Main\Loader::includeModule('iblock');
// создаем объект Query, в качестве параметра передаем объект сущности (свойства)
$query = new Bitrix\Main\Entity\Query(
    Bitrix\Iblock\PropertyTable::getEntity()
);
// выборка
$query->setSelect(array('ID', 'NAME', 'CODE', 'PROPERTY_TYPE'));
// фильтр
$query->setFilter(array('IBLOCK_ID' => 5));
// посмотрим, какой запрос был сформирован
echo '<pre>' . $query->getQuery() . '</pre>';
// выполняем запрос
$result = $query->exec();
// выводим результат
while ($row = $result->fetch()) {
    pp($row);
}

Запрос:

SELECT
    `iblock_property`.`ID` AS `ID`,
    `iblock_property`.`NAME` AS `NAME`,
    `iblock_property`.`CODE` AS `CODE`,
    `iblock_property`.`PROPERTY_TYPE` AS `PROPERTY_TYPE`
  FROM
    `b_iblock_property` `iblock_property`
  WHERE
    `iblock_property`.`IBLOCK_ID` = 5

Ответ:

Array
(
    [ID] => 47
    [NAME] => Автор
    [CODE] => AUTHOR
    [PROPERTY_TYPE] => S
)
Array
(
    [ID] => 48
    [NAME] => Оценка
    [CODE] => RATING
    [PROPERTY_TYPE] => L
)
Array
(
    [ID] => 49
    [NAME] => Галерея
    [CODE] => GALLERY
    [PROPERTY_TYPE] => F
)
Array
(
    [ID] => 51
    [NAME] => Примечание
    [CODE] => NOTE
    [PROPERTY_TYPE] => S
)
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!