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