Главная » Разработка Битрикс » Полезное » CDBResult: Fetch, GetNext, NavStart и постраничка

CDBResult: Fetch, GetNext, NavStart и постраничка

Схема методов объекта CDBResult в старом API 1С-Битрикс

Почти каждый метод старого API Битрикса — CUser::GetList, CIBlockElement::GetList, прямой запрос через $DB->Query — возвращает не готовый массив данных, а объект CDBResult. Разберём, как этот объект устроен и какие его методы регулярно путают между собой.

Fetch vs GetNext

<?php

$result = CUser::GetList('ID', 'ASC', []);

// вариант 1
while ($row = $result->Fetch()) {
    echo $row['LOGIN'];
}

// вариант 2 (для инфоблоков — с дополнительной логикой полей)
while ($row = $result->GetNext()) {
    echo $row['LOGIN'];
}

Fetch() — базовый метод получения следующей строки как ассоциативного массива, доступный у любого объекта CDBResult. GetNext() — специфичный для некоторых наследников (например, результата CIBlockElement::GetList) метод, который дополнительно выполняет форматирование значений полей — например, подстановку полного пути к файлам вместо ID файла. Использование не того метода не вызовет ошибки, но может дать данные в неожиданном формате (сырой ID файла вместо готового пути).

Постраничная навигация: NavStart

<?php

$result = CUser::GetList(
    'ID', 'ASC', [],
    ['NAV_PARAMS' => ['nPageSize' => 20]]
);

$result->NavStart();

while ($row = $result->NavNext()) {
    echo $row['LOGIN'];
}

echo $result->NavPrintPagesBar(); // готовый HTML постраничной навигации

Постраничная навигация встроена прямо в объект результата — NavStart инициализирует текущую страницу (по умолчанию берётся из GET-параметра запроса), NavNext проходит по строкам текущей страницы, а NavPrintPagesBar генерирует готовый блок ссылок постраничной навигации без ручной вёрстки этой логики с нуля.

Нужна помощь с Битрикс?





    Получение общего количества записей

    <?php
    
    echo $result->NavRecordCount; // общее число записей во всей выборке
    echo $result->SelectedRowsCount(); // число строк на текущей странице

    Различие между этими значениями регулярно путают: одно — общее число записей, соответствующих фильтру, по всей выборке целиком, другое — сколько строк реально попало именно в текущую порцию (страницу) результата. Использование не того значения ломает логику вроде "показать общее количество найденных товаров" на странице каталога.

    Прямое обращение к массиву вместо цикла Fetch

    <?php
    
    $items = [];
    $result = CUser::GetList('ID', 'ASC', []);
    
    while ($row = $result->Fetch()) {
        $items[] = $row;
    }
    
    // $items теперь обычный массив, с которым удобнее работать дальше,
    // например, через array_map или array_filter

    Частый практический приём — сразу после получения результата собрать его в обычный PHP-массив через цикл, а не носить объект CDBResult дальше по коду, — обычный массив проще передавать между функциями и обрабатывать стандартными функциями массивов PHP, тогда как объект результата рассчитан именно на последовательный проход, а не на произвольный доступ к элементам.

    Однократность обхода

    Объект CDBResult — это курсор, а не хранилище данных целиком: пройти по нему циклом Fetch() можно только один раз, повторный вызов цикла на том же объекте вернёт пустой результат, поскольку внутренний указатель уже находится в конце. Если данные нужны для повторного использования в нескольких местах кода, их стоит собрать в обычный массив один раз, а не пытаться обойти один и тот же объект результата дважды.

    Частые ошибки

    • Использован Fetch там, где нужен GetNext, или наоборот. Значения полей приходят в сыром виде вместо ожидаемого форматированного, или наоборот.
    • Перепутаны NavRecordCount и SelectedRowsCount. Неверное отображение общего числа найденных записей на странице с пагинацией.
    • Попытка повторно обойти уже пройденный объект результата. Второй проход возвращает пустой результат из-за исчерпанного внутреннего курсора.

    Итог

    CDBResult — курсор для однократного последовательного прохода по результату выборки, а не готовый массив данных. Разница между Fetch и GetNext, а также между общим количеством записей и количеством строк на текущей странице — источник регулярной путаницы, которую стоит держать в голове при работе со старым API Битрикса.

    Нужна помощь с Битрикс?

    Исправим ошибку, доработаем сайт, ускорим Битрикс или поможем разобраться с проблемой.

    Услуги
    Инструменты
    База знаний