Перебор ответа от базы данных в старом ядре
Любой запрос к базе данных с использованием Api Битрикса, будь то GetList()
, GetByID()
или любой другой, в качестве ответа возвращает специальный объект, содержащий данные, выбранные из базы данных. Этот объект, класс CDBResult
, у которого, как и любого другого уважающего себя объекта, есть набор методов, с помощью которых можно обращаться к нему ссылка на документацию. С помощью этих методов можно узнать количество выбранных записей, получить постраничную навигацию и другие результаты запроса. Однако нас интересуют методы, с помощью которых можно получать непосредственно сами данные из этого объекта.
Для получения данных из объекта есть три метода:
Fetch()
GetNext()
GetNextElement()
У объекта CDBResult
нет метода GetNextElement()
, в этой статье мы рассмотрим наследника этого класса, а именно - CIBlockResult. Выбор пал на него по нескольким причинам: во первых, чаще всего вы будете иметь дело с элементами Инфоблоков, где именно этот объект возвращается при запросе методом GetList().
Во-вторых, рассмотрев более частную реализацию объекта, мы охватим и более общий случай.
Что делают методы
Метод Fetch(), берет очередную строку данных, полученных из БД и возвращает ее в виде ассоциативного массива, сдвигая указатель на следующую запись. По сути это бычный mysqli_fetch_assoc()
. Для реализации делаем цикл и поэлементно получаем данные, выбранные запросом.
Возвращает
Возвращают либо ассоциативный массив с полями и свойствами выбранного элемента, либо false
если достигнут конец выборки.
Принимает параметры
Не принимает никаких параметров.
Эта функция - обертка вокруг Fetch()
, она делает то же самое, но возвращает массив полей в ассоциативном виде, преобразуя значения в html-безопасный вид. Помимо этого она создает поля дубликаты с префиксом ~
(тильда), в которых это преобразование не было сделано. Вы можете не боясь выводить результат, полученный этой функцией, из полей без тильды прямо в html, там все уже обеззаражено:
// Из одного поля NAME в массиве получили два
$data = [
'NAME' => 'Функция GetNext',
'~NAME' => 'Функция GetNext'
]
Еще одна особенность этого метода, связанная с объектом CIBlockResult
, преобразование шаблонов url-путей DETAIL_PAGE_URL
, SECTION_PAGE_URL
, LIST_PAGE_URL
, где плейсхолдеры будут заменены реальными значениями из элемента. Таким образом, с помощью этой функции получаем реальные ссылки url для выбранных элементов инфоблоков.
Возвращает
Возвращают либо ассоциативный массив с полями и свойствами выбранного элемента, либо false
если достигнут конец выборки.
Принимает параметры
Принимают два параметра:
public function GetNext($bTextHtmlAuto=true, $use_tilda=true)
- Параметр
$bTextHtmlAuto
boolean
указывает, нужно ли производить html-безопасное преобразование - Параметр
$use_tilda
boolean
указывает, нужно ли добавлять поля с тильдой~
С помощью данных параметров вышеуказанные методы можно приблизить по функциональности к методу Fetch( )
, если поставить два раза false
.
Функция делает то же, что и GetNext()
, но возвращает другое.
Возвращает
Возвращает объект _CIBElement. Этот объект содержит дополнительные методы для того, чтобы получить поля элемента и его свойства.
Принимает параметры
Принимают два параметра:
public function GetNextElement($bTextHtmlAuto=true, $use_tilda=true)
- Параметр
$bTextHtmlAuto
boolean
указывает, нужно ли производить html-безопасное преобразование - Параметр
$use_tilda
boolean
указывает, нужно ли добавлять поля с тильдой~
С помощью данных параметров вышеуказанные методы можно приблизить по функциональности к методу Fetch( )
, если поставить два раза false
.
Теперь, досконально зная каждую из трех функций-близнецов, можно определить, когда нужно применять одну, а когда другую.
- Чаще всего применяйте метод
GetNext()
для получения html-безопасного вида значений полей и ссылок на страницы элементов или разделов инфоблока - Применяйте метод
Fetch()
, если вам не нужно ни то, ни другое - Не применяйте метод
GetNextElement()
, кроме тех случаев, когда вы на 100% уверены, что нужен именно он
Этот порядок ставит вопрос о том, зачем тогда нужен метод GetNextElement()
? Этот метод нужен скорее для максимальный гибкости и настраиваемости, чем для оптимизации и производительности. Он используется в компоненте списка новостей именно для супер-настраиваемости. Создавая свой компонент, скорее всего, вы стремитесь к высокой производительности, поэтому в данном случае этот метод не рекомендуется. Причина заключается в том, что для получения свойств вам придется делать дополнительные запросы в БД, а это совсем не к чему.
Функция Fetch()
- Возвращает ассоциативный массив полей и свойств элемента из выборки, сдвигая указатель в ней на следующий элемент. Либо возвращает
false
, если элементов больше нет - Не принимает никаких параметров
- Использовать этот метод следует тогда, когда не нужно html-безопасное преобразование и/или ссылки
Функция GetNext()
- Делает то же, что и
Fetch()
, дополнительно преобразует поля в html-безопасный вид. Добавляет поля с тильдой (без преобразования к безопасному виду) и преобразует url шаблоны в реальные ссылки, подставляя в них данные - Принимает два параметра:
boolean
для включения/выключения преобразования полей в html-безопасный вид иboolean
для включения/выключения полей с тильдой - Чаще всего нужно использовать этот метод
Функция GetNextElement()
- Делает то же, что и
GetNext()
, только возвращает объект, а не массив, для большей гибкости - Принимает те же параметры, что и
GetNext()
- Применять только в тех случаях, когда нужен именно объект
_CIBElement
, и больше никогда
Примеры
Чтобы правильно применять эти методы чаще всего нужно использовать цикл while
. До тех пор, пока выбранный метод не вернет false
.
GetNext()
$items = [];
$dbItems = CIBlockElement::GetList(... Тут параметры ...);
while ($item = $dbItem->GetNext()) {
// как-то обрабатываем массив $item
...
// формируем итоговый список элементов
$items[] = $item;
}
Fetch()
$items = [];
$dbItems = CIBlockElement::GetList(... Тут параметры ...);
while ($item = $dbItem->Fetch()) {
// как-то обрабатываем массив $item
...
// формируем итоговый список элементов
$items[] = $item;
}
GetNextElement()
while ($item = $dbItem->GetNextElement()) {
$element = $item->GetFields();
$element['PROPERTIES'] = $item->GetProperties();
// как-то обрабатываем массив $element
...
// формируем итоговый список элементов
$items[] = $element;
}