- Как вывести произвольный контент в шаблоне сайта и компонента
- Выводим компонент в шаблоне другого компонента
- component_epilog.php и кеширование не работают вместе
- Пример работы с SetViewTarget
- ShowViewContent в bitrix
Можно использовать как в шаблоне сайта, так и в шаблоне компонента. Теперь есть поддержка стандартного кеширования в компонентах.
- Размещаем в нужном месте отложенную функцию. Она поставит #МЕТКУ#, которая позже будет заменена результатом выполнения откладываемого кода.
# header.php:
<div id="sidebar">
<?$APPLICATION->ShowViewContent("sidebar")?>
</div>
- Код, выполнение которого необходимо отложить, оборачиваем в конструкцию:
# template.php:
<?$this->SetViewTarget("sidebar");?>
<div class="element-filter">
<!--вывод фильтра-->
</div>
<?$this->EndViewTarget();?>
# component_epilog.php:
<?$this->__template->SetViewTarget('content_id')?>
<!--here your code-->
<?$this->__template->EndViewTarget()?>
Если не работает при включенном кэшировании, необходимо выполнить метод InitComponentTemplate():
<?if(!$this->__template) $this->InitComponentTemplate();?>
Методы, доступные в шаблоне (через $this):
- CBitrixComponentTemplate::SetViewTarget($view, $pos)
- CBitrixComponentTemplate::EndViewTarget()
Методы глобального объекта $APPLICATION:
- Cmain::AddViewContent($view, $content, $pos)
- Cmain::ShowViewContent($view)
где:
- $view – идентификатор буферизируемой области;
- $content – буферизируемый контент;
- $pos – сортировка вывода контента.
Примечание: одному идентификатору $view может соответствовать несколько буферов. Последовательность вывода контента определяется сортировкой $pos.
https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43&LESSON_ID=3855
Вывести компонент в шаблоне другого компонента, при условии включенного кэширования Битрикс.
Основная проблема вложенных компонентов заключается в том, что при включенном кэшировании код вложенных компонентов выполняться не будет и соответственно актуализации данных не произойдет без очистки кэша основного компонента.
Для решения этой проблемы можно воспользоватья файлом component_epilog.php
-
Добавим метку в шаблон основного компонента (template.php)
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die(); $this->setFrameMode(true); // начинаем буферизацию вывода ob_start(); // тут разметка и код основного компонента, а в нужном месте вставляем метку: #INNER_BLOCK_1# <? // передаем данные буфера вывода в файл component_epilog.php $this->__component->SetResultCacheKeys(array("CACHED_TPL")); $this->__component->arResult["CACHED_TPL"] = @ob_get_contents(); ob_get_clean(); ?>
-
Вынесем в файл component_epilog.php основного компонента вызов вложенного компонента и всей нужной разметки
<? require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/header.php"); /** * @var CMain $APPLICATION * @var array $arResult */ // callback function $replacer = function ($matches) use ($APPLICATION) { ob_start(); // тут вставляем разменту, вызовы компонентов, в общем все что нужно вывести // в метке #INNER_BLOCK_123# мы можем передать в качестве числа например код инфоблока // и использовать его так : $id = $matches[1]; // например в вызове компонента списка новостей: $APPLICATION->IncludeComponent( "bitrix:news.list", "article-list", Array( 'IBLOCK_ID' => $id, // тут миллион параметров компонента ) ); return ob_get_clean(); }; // находим метку и заменяем ее на результат работы нашей функции echo preg_replace_callback( "/#INNER_BLOCK_([\\d]+)#/is" . BX_UTF_PCRE_MODIFIER, $replacer, $arResult["CACHED_TPL"] );
-
В шаблоне первого компонента
<? $this->setViewTarget('view_marker'); ?> тут код шаблона компонента <? $this->endViewTarget(); ?>
-
В шаблоне второго компонента
<?= $APPLICATION->getViewContent('view_marker') ?>
https://gdecider.github.io/articles-bx-inner-component.html
Когда отрабатывается catalog.section, внутри срабатывает вызов генерации строки навигации. Но так как этот вызов происходит внутри той части кода, которая кэшируется, то при повторном обращении к странице и работе catalog.section из кэша, второй раз вызов не происходит. Следовательно - бесполезно пытаться добавить component_epilog.php к шаблону строки навигации.
Подозреваю, что вы хотите сделать rel=canonical
или что-то подобное? Если так, то тут нужно действовать по-другому. После того, как отрабатывает компонент catalog.section, в $arResult появляется поле NAV_RESULT
($arResult["NAV_RESULT"]). Это поле содержит всю информацию о постраничной навигации.
Следовательно вам нужно работать с component_epilog.php компонента catalog.section, а не system.pagenavigation. В эпилоге вы вытаскиваете $arResult["NAV_RESULT"] и, опираясь на него, делаете, что вам нужно. Например, в моём случае имел место кусок кода:
if (!$arResult['NAV_RESULT']["NavShowAll"]) {
$APPLICATION->AddHeadString('<link rel="canonical" href="' . $arResult['NAV_RESULT']['sUrlPath'] . '?'
. $strNavQueryString . 'SHOWALL_' . $arResult['NAV_RESULT']['NavNum'] . '=1" >');
}
А ещё, может быть кому-то будет полезно, по теме есть другая штука. Я знаю ещё один случай, когда component_epilog.php не отрабатывает - это компонент search.page. Может быть, я глупо пытался использовать его в режиме кэширования, но голову я себе тогда сломал основательно. Оказалось, он использует не стандартный вызов IncludeComponentTemplate, а связку
if ($this->InitComponentTemplate($templatePage)) {
// ...
$this->ShowComponentTemplate();
}
Как мне объяснили в техподдержке - это старый вариант вызова шаблона (кстати, он позволяет делать интересные штуки. кому интересно - почитайте код вышеупомянутого компонента). Переделывать на новый (который поддерживает component_epilog.php) не стали, так как использование компонента в режиме кэширования не предполагается. Больше никакой магии с component_epilog.php мне не известно.
https://dev.1c-bitrix.ru/support/forum/messages/forum6/topic58419/message363387/#message363387
В ядре продукта 1С-Битрикс имеется замечательный метод CMain::ShowViewContent
, который позволяет установить выводимый контент для функции AddViewContent
. С помощью этого метода можно вывести компонент, где угодно. Допустим, мы используем комплексный компонент bitrix:catalog, и фильтр у нас будет вызываться в файле шаблона section.php. Тогда вызов фильтра должен быть таким:
if (!isset($_REQUEST["ajax"])) $this->SetViewTarget("sidebar");
$APPLICATION->IncludeComponent(
"bitrix:catalog.smart.filter",
"",
array(...),
false
);
if(!isset($_REQUEST["ajax"])) $this->EndViewTarget("sidebar");
Т.е. перед фильтром мы вызываем метод SetViewTarget
, после EndViewTarget
. В результате фильтр отработает ДО компонента bitrix:catalog.section, но показан он не будет. Затем в том месте, где мы хотим отобразить фильтр, необходимо вызвать метод:
$APPLICATION->ShowViewContent('sidebar');
Это может быть любым местом: шаблон сайта, шаблон другого компонента, включаемая область.
Для задания контента, который должен быть помещен в определенную область с помощью отложенной функции, необходимо воспользоваться конструкцией:
ob_start();
echo 'SomeText';
$content = ob_get_clean();
$APPLICATION->AddViewContent('content', $content); ?>
Воспользоваться конструкцией $this->SetViewTarget
из файла component_epilog.php не удастся, т.к. в данном файле это уже объект класса CBitrixComponent (а не CBitrixComponentTemplate, как в файле template.php). В таком случае нужно использовать конструкцию вида:
<?$this->__template->SetViewTarget('mdf_title');?>
same text here ...
<?$this->__template->EndViewTarget();?>
https://pai-bx.com/wiki/1c-bitrix/29-example-of-setviewtarget/
Чтобы передать данные, например, из шаблона компонента в шаблон сайта, можно воспользоваться функционалом отложенных функций.
ShowViewContent
- это обычная отложенная функция, такая же как и SetTitle
или SetPageProperty
. Поэтому вывод контента с помощью ShowViewContent
может быть выше по коду, чем передача самого контента с помощью AddViewContent
или с помощью SetViewTarget + EndViewTarget
.
Передаём контент в буферизируемую область:
$APPLICATION->AddViewContent('myContentBlockName', '<p>Hello</p>');
И указываем, где нужно выводить содержимое этой буферизируемой области, но только в некешируемой части (например, в шаблоне сайта):
$APPLICATION->ShowViewContent('myContentBlockName');
- Если не будет выполнено ни одного
AddViewContent
, то в месте выводаShowViewContent
будет пусто. - Если не будет выполнен метод
ShowViewContent
, то контент переданный вAddViewContent
не будет выведен нигде. - Если метод
ShowViewContent
будет выполнен в разных местах или, например, несколько раз подряд, то контент будет продублирован в каждом из этих мест.
При этом можно добавлять сколько угодно частей контента:
$APPLICATION->AddViewContent('myContentBlockName', '<p>Hello</p>');
$APPLICATION->AddViewContent('myContentBlockName', '<p>World</p>');
$APPLICATION->AddViewContent('myContentBlockName', '<p>!</p>');
Позиционировать выводимые части контента можно с помощью веса (третьего аргумента):
$APPLICATION->AddViewContent('myContentBlockName', '<span>world!</span>', 600);
$APPLICATION->AddViewContent('myContentBlockName', '<span>Hello, </span>', 500);
Как и все отложенные функции AddViewContent
можно использовать только в некешируемой области, т.е. в component_epilog.php. Но в шаблоне компонента даже в кешируемой области в файлах template.php и result_modifier.php можно использовать методы SetViewTarget + EndViewTarget
:
<?$this->SetViewTarget('myContentBlockName');?>
<p>Hello</p>
<?$this->EndViewTarget();
Можно комбинировать SetViewTarget + EndViewTarget
и AddViewContent
. Например, в template.php передаём одну часть:
// в этом методе тоже есть возможность указать вес (второй аргумент)
<?$this->SetViewTarget('myContentBlockName', 600);?>
<span>world</span>
<?$this->EndViewTarget();?>
А в component_epilog.php другую:
<?$APPLICATION->AddViewContent( 'myContentBlockName', '<span>Hello, </span>', 500);?>