Битрикс. Отложенные функции
08.12.2018
Теги: CMS • Web-разработка • Битрикс • Буферизация • ОтложенныеФункции
Отложенные функции — технология, позволяющая задавать заголовок страницы, пункты навигационной цепочки, CSS стили, дополнительные кнопки в панель управления, мета-теги и т.п. с помощью функций, используемых непосредственно в теле страницы. Соответствующие результаты работы этих функций выводятся в прологе, то есть выше по коду, чем они были заданы.
Технология была создана в первую очередь для использования в компонентах, которые, как правило, выводятся в теле страницы, но при этом внутри них могут быть заданы заголовок страницы, добавлен пункт в навигационную цепочку, добавлена кнопка в панель управления и так далее. Отложенные функции нельзя использовать в файлах шаблона компонента template.php
и result_modifier.php
(так как результаты их выполнения кешируются).
Алгоритм работы
Любой исходящий поток из PHP скрипта буферизируется. Как только в коде встречается одна из следующих функций:
CMain::ShowTitle()
CMain::ShowCSS()
CMain::ShowNavChain()
CMain::ShowProperty()
CMain::ShowMeta()
CMain::ShowPanel()
Весь буферизированный до этого контент запоминается в очередном элементе стека КонтентСтраницы. И сразу полсе этого в стек КонтентСтраницы добавляется пустой элемент. В дальнейшем этот пустой элемент будет заполнен результатом выполнения отложенной функции. Имя этой отложенной функции запоминается в стеке ОтложенныеФункции. Буфер очищается и буферизация снова включается.
Таким образом, существует стек КонтентСтраницы, в котором находится весь контент страницы, разбитый на части. В этом же стеке есть пустые элементы, предназначенные для их дальнейшего заполнения результатами отложенных функций. Также существует стек ОтложенныеФункции, в котором запоминаются имена и параметры отложенных функции в порядке их следования в коде.
В конце страницы, в служебной части эпилога, выполняются следующие действия:
- все отложенные функции из стека ОтложенныеФункции начинают выполняться одна за другой;
- результаты их выполнения вставляются в специально предназначенные для этого места в стек КонтентСтраницы;
- весь контент из стека КонтентСтраницы «склеивается» (конкатенируется) и выводится на экран.
Таким образом, технология позволяет фрагментировать весь контент страницы, разбивая его на части с помощью специальных функций, обеспечивающих временное откладывание выполнения других функций. В конце страницы все отложенные функции выполняются одна за другой и результаты их выполнения вставляются в отведенные для этого места внутри фрагментированного контента страницы. Затем весь контент склеивается и отправляется браузеру посетителя сайта.
Пример использования
Давайте рассмотрим пример установки заголовка страницы и заголовка окна браузера.
<?php /* * Файл /local/templates/page/header.php */ if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die(); ?> <!DOCTYPE html> <html> <head> <title><?php $APPLICATION->ShowTitle(); /* показываем заголовок браузера */ ?></title> </head>
<?php /* * Файл /test/index.php */ require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php"); ?> <h1><?php $APPLICATION->ShowTitle(false); /* показываем заголовок страницы */ ?></h1> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <?php require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php"); ?>
Поскольку мы нигде не вызываем методы SetTitle()
и SetPageProperty()
, заголовок браузера и заголовок страницы у нас пустые. Давайте установим значения заголовков:
<?php require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php"); // устанавливаем заголовок страницы $APPLICATION->SetTitle('Какой-то заголовок (старый)'); // устанавливаем заголовок браузера $APPLICATION->SetPageProperty('title', 'Какой-то заголовок (старый)'); ?> <h1><?php $APPLICATION->ShowTitle(false); /* показываем заголовок страницы */ ?></h1> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <?php require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php"); ?>
Переопределим значения заголовков браузера и страницы ниже по коду:
<?php require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php"); // устанавливаем заголовок страницы $APPLICATION->SetTitle('Какой-то заголовок (старый)'); // устанавливаем заголовок браузера $APPLICATION->SetPageProperty('title', 'Какой-то заголовок (старый)'); ?> <h1><?php $APPLICATION->ShowTitle(false); /* показываем заголовок страницы */ ?></h1> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <?php // устанавливаем заголовок страницы $APPLICATION->SetTitle('Какой-то заголовок (новый)'); // устанавливаем заголовок браузера $APPLICATION->SetPageProperty('title', 'Какой-то заголовок (новый)'); ?> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <?php require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php"); ?>
В компонентах Битрикс часто можно увидеть такой код, который устанавливает значения заголовков и значенния мета-тегов keywords
и description
:
if ($this->StartResultCache(false, ($arParams['CACHE_GROUPS']==='N' ? false: $USER->GetGroups()))) { /* * Данных в кеше нет, выполняем запрос к БД */ /* ...получаем данные... */ if (isset($arResult['ID'])) { // данные успешно получены $this->SetResultCacheKeys( array( 'ID', 'NAME', 'IPROPERTY_VALUES' ) ); $this->IncludeComponentTemplate(); } else { // что-то пошло не так $this->AbortResultCache(); \Bitrix\Iblock\Component\Tools::process404( trim($arParams['MESSAGE_404']) ?: 'Элемент инфоблока не найден', true, $arParams['SET_STATUS_404'] === 'Y', $arParams['SHOW_404'] === 'Y', $arParams['FILE_404'] ); } } // кэш не затронет все действия ниже, здесь работаем уже с другим $arResult if (isset($arResult['ID'])) { if ($arParams['SET_PAGE_TITLE'] == 'Y') { // установить заголовок страницы? if ($arResult['IPROPERTY_VALUES']['ELEMENT_PAGE_TITLE'] != '') { $APPLICATION->SetTitle($arResult['IPROPERTY_VALUES']['ELEMENT_PAGE_TITLE']); } else { $APPLICATION->SetTitle($arResult['NAME']); } } if ($arParams['SET_BROWSER_TITLE'] == 'Y') { // установить заголовок окна браузера? if ($arResult['IPROPERTY_VALUES']['ELEMENT_META_TITLE'] != '') { $APPLICATION->SetPageProperty('title', $arResult['IPROPERTY_VALUES']['ELEMENT_META_TITLE']); } else { $APPLICATION->SetPageProperty('title', $arResult['NAME']); } } // установить мета-тег keywords? if ($arParams['SET_META_KEYWORDS'] == 'Y' && $arResult['IPROPERTY_VALUES']['ELEMENT_META_KEYWORDS'] != '') { $APPLICATION->SetPageProperty('keywords', $arResult['IPROPERTY_VALUES']['ELEMENT_META_KEYWORDS']); } // установить мета-тег description? if ($arParams['SET_META_DESCRIPTION'] == 'Y' && $arResult['IPROPERTY_VALUES']['ELEMENT_META_DESCRIPTION'] != '') { $APPLICATION->SetPageProperty('description', $arResult['IPROPERTY_VALUES']['ELEMENT_META_DESCRIPTION']); } return $arResult['ID']; }
Методы ShowViewContent и AddViewContent
Метод CMain::ShowViewContent()
добавляет в стек КонтентСтраницы пустой элемент. А метод CMain::AddViewContent()
добавляет в этот элемент контент, который формируется ниже:
<?php require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php"); ?> <h1>Случайные элементы</h1> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <?php // здесь выводим контент с меткой «random-elements», который будет сфорирован ниже $APPLICATION->ShowViewContent('random-elements'); ?> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <?php // включаем буферизацию вывода, все идет в отдельный буфер ob_start(); // вызываем компонент, который формирует список блок случайных элементов инфоблока $GLOBALS['APPLICATION']->IncludeComponent( "tokmakov:iblock.random", "", Array( "ELEMENT_COUNT" => "4", "ELEMENT_URL" => "#SITE_DIR#/#IBLOCK_CODE#/element/code/#ELEMENT_CODE#/", "IBLOCK_ID" => "5", "IBLOCK_TYPE" => "content" ) ); // выключаем буферизацию и помечаем этот контент меткой «random-elements» $APPLICATION->AddViewContent('random-elements', ob_get_clean()); ?> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore... </p> <?php require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php"); ?>
Методы SetViewTarget и EndViewTarget
В шаблоне компонента вместо функций ob_start()
и ob_get_clean()
можно использовать методы SetViewTarget()
и EndViewTarget()
:
<?php // включаем буферизацию и помечаем этот контент меткой «smart-filter» $this->SetViewTarget('smart-filter'); ?> <div class="smart-filter"> <?php $APPLICATION->IncludeComponent( 'bitrix:catalog.smart.filter', '', Array( // параметры компонента ), $component ); ?> </div> <?php // выключаем буферизацию $this->EndViewTarget(); ?>
В том месте, где нам нужно вывести контент, добавляем в стек КонтентСтраницы пустой элемент:
<div class="left sidebar"> <?php $APPLICATION->ShowViewContent('smart-filter'); ?> </div>
Поиск: CMS • Web-разработка • Битрикс • Буферизация • Отложенные функции • ShowTitle • ShowCSS • ShowNavChain • ShowProperty • ShowMeta • ShowPanel • ShowViewContent • AddViewContent • SetViewTarget • EndViewTarget