Yandex Metrika
sanches.free 23 просмотра

Выборка элементов, разделов и инфоблоков через GetList: фильтры, документооборот и пагинация

Где смотреть поля и таблицы

Структура модуля iblock описана в документации по полям: какие столбцы у элементов, разделов и версий есть в базе и как они отражены в фильтрах. Это полезно, когда нужно понять, почему GetList «молчит» при видимости записи через прямой SQL.

Элементы: CIBlockElement::GetList

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

Для поиска по символьному коду почти всегда нужно точное сравнение: в фильтре ключ =CODE, а не CODE. В последнем случае движок превращает условие в LIKE с подстановкой символов SQL-шаблона.

$sortSpec = ['SORT' => 'ASC'];
$filterSpec = [
    'IBLOCK_ID' => $portfolioIblockPk,
    'ID' => $detailElementPk,
    'ACTIVE' => 'Y',
    'ACTIVE_DATE' => 'Y',
    '=PROPERTY_PROMO_TOGGLE' => 'Y',
];
$columnSpec = [
    'ID',
    'CODE',
    'NAME',
    'PREVIEW_PICTURE',
    'DETAIL_PICTURE',
    'PREVIEW_TEXT',
    'DETAIL_TEXT',
    'PROPERTY_BROCHURE',
    'ACTIVE_FROM',
    'ACTIVE_TO',
];

$navigator = false;
$elementCursor = CIBlockElement::GetList(
    $sortSpec,
    $filterSpec,
    false,
    $navigator,
    $columnSpec
);

while ($row = $elementCursor->Fetch()) {
    /* обработка $row */
}

Документооборот и черновики

Если инфоблок подключён к цепочке согласования, новые ревизии могут висеть как «ещё не опубликованные». Обычный GetList их не вернёт. Для смешанной выборки добавляют в фильтр 'SHOW_NEW' => 'Y'. Последнюю рабочую копию в цепочке иногда берут точечным вызовом CIBlockElement::WF_GetLast() — когда нужен именно хвост workflow, а не полный список.

Счёт строк в БД без версий документа

Если в таблице есть поле связи версий родителя, «живые» строки элементов считают по связке родителя, обнуляющуюся только у корневой записи:

SELECT COUNT(*) AS tally
FROM b_iblock_element
WHERE IBLOCK_ID = ?
  AND WF_PARENT_ELEMENT_ID IS NULL;

Плейсхолдер ? передаётся через параметризованный запрос на стороне приложения.

Разделы: CIBlockSection::GetList

Вторым аргументом иногда передают $bIncCnt — пересчёт количества элементов в разделе; для тяжёлых деревьев его лучше не включать без необходимости. Пользовательские поля раздела в $arSelect называются с префиксом UF_* и должны быть заведены в настройках инфоблока.

$sortSpec = ['LEFT_MARGIN' => 'ASC'];
$filterSpec = [
    'IBLOCK_ID' => $faqIblockPk,
    'SECTION_ID' => $parentSlicePk,
    'DEPTH_LEVEL' => 2,
];
$columnSpec = ['ID', 'NAME', 'UF_ICON_TOKEN', 'UF_BADGE_NOTE'];

$sliceCursor = CIBlockSection::GetList(
    $sortSpec,
    $filterSpec,
    false,
    $columnSpec,
    false
);

while ($slice = $sliceCursor->Fetch()) {
    /* обработка $slice */
}

Сами инфоблоки: CIBlock::GetList

Это уже выборка описателей типов блоков в текущей языковой связке: в фильтре участвуют TYPE, привязка к сайту, активность записи описателя. Типичная ошибка с чужих шпаргалок — подставить в этот метод ключ IBLOCK_ID как у элементов. Для точечного блока нужен ключ ID (номер описателя инфоблока), а для перечисления каталогов на сайте фильтруют по LID, ACTIVE и при необходимости TYPE.

$sortSpec = ['SORT' => 'ASC'];
$filterSpec = [
    'ID' => $docsIblockPk,
    'SITE_ID' => SITE_ID,
    'ACTIVE' => 'Y',
];
$iblockWalker = CIBlock::GetList($sortSpec, $filterSpec, false);

if ($meta = $iblockWalker->Fetch()) {
    /* $meta['ID'] можно передать как IBLOCK_ID в выборках элементов */
}

Для списка всех активных блоков сайта ограничивают не IBLOCK_ID элементного уровня, а условием по типу и привязке: TYPE, LID или «сайтовым» ключам из актуальной справочной таблицы полей фильтра.

Фильтр пользователей по числовому ключу

В выборках пользовательского слоя давно есть отдельное имя фильтра для строгого сравнения по целому идентификатору. Для многих задач следует использовать =ID либо (в зависимости от версии и контекста) эквивалент «точного» ключа вида ID_EQUAL_EXACT, а не голый листовой ID, чтобы не получить диапазонное поведение в обёрнутых API.

Пагинация в компоненте

Когда $arResult['ITEMS'] — это объект постраничной выборки, вывести текстовую строку переходов можно через стандартную обвязку навигатора. Ни минимальный скелет без лишнего HTML:

$arResult['ITEMS']->NavStart(25, false);
$arResult['PAGE_CHAIN'] =
    $arResult['ITEMS']->GetPageNavStringEx(
        $componentTemplate,
        'Новости',
        'pager_new',
        'Y'
    );
/* сравните $arResult["ITEMS"]->NavRecordCount с порогом, если цепочку скрывают */

Связь с D7

Для новых сервисных модулей выгоднее ORM элементов и разделов: меньше сюрпризов с префиксами PROPERTY_* и проще статический анализ. Легаси GetList всё равно остаётся в эксплуатационных скриптах, генераторах контента и кастомных компонентах — знание фильтров и документооборота экономит время на отладке «пустого» результата.

Итог

  • Для кода свойств и символьных полей элементов добавляют = там, где нужно точное совпадение.
  • Черновики workflow ищут с SHOW_NEW или через WF_GetLast().
  • Разделы тянут UF_* напрямую в select.
  • Для описателей инфоблока не смешивают синтаксис фильтров с уровнем элементов.

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии