Отложенные функции
Отложенные функции — технология, позволяющая задавать заголовок страницы, пункты навигационной цепочки, CSS стили, дополнительные кнопки в панель управления, мета-теги и т.п. с помощью функций, используемых непосредственно в теле страницы. Соответствующие результаты работы этих функций выводятся в прологе, то есть выше по коду, чем они были заданы.
Технология была создана в первую очередь для использования в компонентах, которые, как правило, выводятся в теле страницы, но при этом внутри них могут быть заданы заголовок страницы, добавлен пункт в навигационную цепочку, добавлена кнопка в панель управления и так далее.
Отложенные функции нельзя использовать в файлах шаблона компонента template.php
и result_modifier.php
, результаты выполнения этих файлов кешируются.
Алгоритм работы
Любой исходящий поток из PHP скрипта буферизируется. Как только в коде встречается одна из следующих функций:
CMain::ShowTitle()
CMain::ShowCSS()
CMain::ShowNavChain()
CMain::ShowProperty()
CMain::ShowMeta()
CMain::ShowPanel()
Весь буферизированный до этого контент запоминается в очередном элементе стека КонтентСтраницы
. И сразу полсе этого в стек КонтентСтраницы
добавляется пустой элемент. В дальнейшем этот пустой элемент будет заполнен результатом выполнения отложенной функции. Имя этой отложенной функции запоминается в стеке ОтложенныеФункции
. Буфер очищается и буферизация снова включается.
Таким образом, существует стек КонтентСтраницы
, в котором находится весь контент страницы, разбитый на части. В этом же стеке есть пустые элементы, предназначенные для их дальнейшего заполнения результатами отложенных функций. Также существует стек ОтложенныеФункции
, в котором запоминаются имена и параметры отложенных функции в порядке их следования в коде.
В конце страницы, в служебной части эпилога, выполняются следующие действия:
- все отложенные функции из стека
ОтложенныеФункции
начинают выполняться одна за другой - результаты их выполнения вставляются в специально предназначенные для этого места в стек
КонтентСтраницы
- весь контент из стека
КонтентСтраницы
«склеивается» (конкатенируется) и выводится на экран
Таким образом, технология позволяет фрагментировать весь контент страницы, разбивая его на части с помощью специальных функций, обеспечивающих временное откладывание выполнения других функций. В конце страницы все отложенные функции выполняются одна за другой и результаты их выполнения вставляются в отведенные для этого места внутри фрагментированного контента страницы. Затем весь контент склеивается и отправляется браузеру посетителя сайта.
Пример использования с заголовками
Давайте рассмотрим пример установки заголовка страницы и заголовка окна браузера:
header.php<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) die();
?>
<!DOCTYPE html>
<html>
<head>
<title>
<?
// показываем заголовок браузера
$APPLICATION->ShowTitle();
?>
</title>
</head>
Поскольку мы нигде не вызываем методы SetTitle()
, заголовок браузера и заголовок страницы у нас пустые. Давайте установим значения заголовков:
index.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");
?>
Пример использования в своем компоненте
В компонентах Битрикс часто можно увидеть такой код, который устанавливает значения заголовков и значенния мета-тегов keywords
и description
:
class.php<?
if ($this->StartResultCache()) {
//****************//
// Код компонента //
//****************//
// получаем данные раздела SEO
$ipropElementValues = new \Bitrix\Iblock\InheritedProperty\ElementValues($arResult["IBLOCK_ID"], $arResult["ID"]);
$arResult["SEO"] = $ipropElementValues->getValues();
// кэш не затронет весь код ниже, он будут выполняться на каждом хите, здесь работаем с другим $arResult, будут доступны только те ключи массива, которые перечислены в вызове SetResultCacheKeys()
if (isset($arResult['ID'])) {
// ключи $arResult перечисленные при вызове этого метода, будут доступны в component_epilog.php и ниже по коду, обратите внимание там будет другой $arResult
$this->SetResultCacheKeys(
array(
'SEO'
)
);
$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']
);
}
}
// устанавливаем метатеги
if (isset($arResult['ID'])) {
// делаем $APPLICATION глобальной переменной
global $APPLICATION;
// устанавливаем заголовок окна браузера title
if (isset($arResult["SEO"]["ELEMENT_META_TITLE"]) && $arResult["SEO"]["ELEMENT_META_TITLE"] != "") {
$APPLICATION->SetTitle($arResult["SEO"]["ELEMENT_META_TITLE"]);
}
// устанавливаем заголовок страницы h1
if (isset($arResult["SEO"]["SECTION_PAGE_TITLE"]) && $arResult["SEO"]["SECTION_PAGE_TITLE"] != "") {
$APPLICATION->SetPageProperty("H1", $arResult["SEO"]["SECTION_PAGE_TITLE"]);
}
// устанавливаем мета-тег keywords
if (isset($arResult["SEO"]["ELEMENT_META_KEYWORDS"]) && $arResult["SEO"]["ELEMENT_META_KEYWORDS"] != "") {
$APPLICATION->SetPageProperty("keywords", $arResult["SEO"]["ELEMENT_META_KEYWORDS"]);
}
// устанавливаем мета-тег description
if (isset($arResult["SEO"]["ELEMENT_META_DESCRIPTION"]) && $arResult["SEO"]["ELEMENT_META_DESCRIPTION"] != "") {
$APPLICATION->SetPageProperty("description", $arResult["SEO"]["ELEMENT_META_DESCRIPTION"]);
}
}
Для вывода h1
в нужной части страницы:
<h1><? $APPLICATION->ShowTitle('H1') ?></h1>
Пример использования в шаблоне компонента
В шаблоне компонента можно использовать методы SetViewTarget()
и EndViewTarget()
:
template.php<?
// включаем буферизацию и помечаем этот контент меткой smart-filter
$this->SetViewTarget('smart-filter');
?>
<div class="smart-filter">
<?
// подключаем компонент
$APPLICATION->IncludeComponent(
'bitrix:catalog.smart.filter',
'',
Array(
),
// обязательный параметр если вызывать компонент внутри другого компонента
$component
);
?>
</div>
<?
// выключаем буферизацию
$this->EndViewTarget();
?>
В том месте, где нам нужно вывести контент, добавляем в стек пустой элемент:
index.php<? $APPLICATION->ShowViewContent('smart-filter'); ?>