Тему моего первого поста в блоге навеяли темы на форуме, в которых обсуждалось как устанавливать заголовок страницы из компонента который кешируется.
Очень часто в целях поисковой оптимизации требуется установить особенный заголовок, не такой как у $arResult["NAME"], а например "Холодильники ".$arResult["NAME"]; и др.
Или нам требуется установить картинку раздела из компонента. Допустим на сайте есть внутренний вижуал, который меняется в зависимости от выбранного автомобиля. Пример. [spoiler] В этом случае мы в компоненте анализируем свойство "Картинка" у автомобиля, и ставим его в качестве картинки раздела. Поскольку компонент в коде шаблона находится ниже чем картинка, делать это надо с помощью отложенных функций. Т.е. в компоненте досдаточно вызвать $APPLICATION->SetPageProperty("cat_pic", "/images/mypic.jpg"); а потом в шаблоне вывести это свойство с помощью отложенной функции.
Но если компонент кешируется, то ни в его шаблоне, ни в result_modifier.php вызов $APPLICATION->SetPageProperty() не сработает.
Преимущества стандартных компонентов:
1) Сохраняются все преимущества обновления (а их в последнее время все больше и больше, например, ЧПУ с поддержкой символьных кодов).
2) Шаблоны гораздо легче и проще переносить из проекта в проект, чем самописные компоненты.
3) Стандартные компоненты проверены тысячами сайтов, и я уверен в их надежности и безопасности.
Вобщем, перейдем к делу.
Чтобы это все сработало - нам надо в файле result_modifier.php написать:
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
// Картинка категории - это картинка связанного элемента
if ($arResult["LINKED_ELEMENTS"][0]["ID"] > 0)
{
$el = CIblockElement::GetById($arResult["LINKED_ELEMENTS"][0]["ID"]);
$element = $el->GetNext();
if ($element["DETAIL_PICTURE"] > 0)
$pic = CFile::GetPath($element["DETAIL_PICTURE"]);
}
// Приклеиваем путь к картинке к ID элемента
$component = $this->__component;
$component->arResult["ID"] = $arResult["ID"]."|".$pic;
?>
Вся хитрость в том, что строчкой $component->arResult["ID"] = $arResult["ID"]."|".$pic; мы приклеиваем к результату работы компонента свои параметры.
При вызове компонента в шаблоне сайта результат его работы записываем в переменную $element_id:
<?$element_id=$APPLICATION->IncludeComponent("bitrix:catalog.element", "security", array(
... код вызова компонента ...
а после кода вызова компонента разбираем полученную строчку:
$arReturn = explode('|', $element_id);
if ($arReturn[1])
$APPLICATION->SetDirProperty("cat_pic", $arReturn[1]);
Чтобы сохранить совместимость, нам нужно чтобы на выходе компонента мы получили $ID элемента. Он используется при редактировании элементв "с лица". А поскольку все компоненты Битрикса, как я говорил, написаны очень грамотно и безопасно - во всех них делается проверка $ID = intval($ID); Поэтому система получает нормальный $ID и ничего лишнего.
Мы же можем разрбрать строку $ID, вытащить из неё картинку или любое другое свойство (или даже несколько свойств), и с помощью отложенных функций дальше делать с ними все что угодно.
Компоненты, настроенные таким образом, отлично кешируются, заголовки и свойства динамически устанавливаются и можно добиться чтобы сайт работал даже без соединения с базой данных.
Недостатки (а есть и такие):
1) Не все компоненты что-то возвращают. Хотя большинство элементов все же возвращают значения, есть и такие которые почему-то этого не делают. Так, элемент bitrix:catalog.sections почему-то в случае успеха возвращает 1, а не номер раздела.
Выход: использовать компонент bitrix:photo.section, он делает все правильно и возвращает номер раздела. Или же искать другой путь обхода.
2) При использовании визуального редактора если стоит строчка <?$element_id = $APPLICATION->IncludeComponent(... ?> то редактор не понимает что это компонент, и вместо него выводит код <?php?>. Что довольно странно, мне даже помнится раньше такое срабатывало. Надеюсь, в будущем разработчики исправят этот досадный недостаток, так как системой предусмотрено чтобы компоненты что-то возвращали, и это коррекнтный вызов компонента.
Выход: использовать такую конструкцию в комплексных компоненентах. Тогда в файле element.php можно подключать сразу несколько компонентов, и дописывать до и после них любой код, не переживая за визуальный редактор.
Еще один вариант - редактировать параметры компонентов перейдя на вкладку "Разработка" и нажав на "шестеренку". Компоненты, измененные таким образом отлично сохраняются и $element_id перед ними остается.
Все-же надеюсь в будущем разработчики добавят событие, или файл-обработчик в котором можно будет вызывать свои функции, а пока пользюсь этим методом, и очень доволен
UPD: На данный момент я на всех проектах использую "Супер компонент", в котором можно устанавливать любые динамические свойства из файла result_modifier_nc.php.
Я тут хотел показать как можно обойтись без использования дополнительных компонентов или модификации стандартных.
Да, тут можно было сделать установку свойств и через меню. Но у нас не всегда будет такое меню из которого можно устанавливать свойства для всех нужных нам страниц.
И это немного нарушает идеологию, и другому разработчику может быть сложно разобраться что же все таки устанавливает эту картинку.
А так и заголовок, и ключевые слова, и картинку раздела, и все остальное устанавливает сам компонент каталога.
Цель меню - построить пункты чтобы по ним можно было вести навигацию.
Цель каталога - вывести элемент. Элемент устанавливает заголовок страницы, ключевые слова на странице, и картинку раздела, которая берется из свойств элемента.
Можно конечно и через меню ставить заголовок, можно и вообще через init.php, но "компонентный похдод" предолагает что и заголовок, и слова, и картинку должен ставить элемент.
Если элемент на странице есть - он вносит изменения. Если его нету - не вносит. Не пойму зачем сюда вмешивать меню, оно из другой оперы.
Файл bitrix:menu.sections вообще не подойдет если мы имеем дело с элементами. Так как он работает только с разделами.
А если писать свой элемент menu_ext.php то понятно что мы в нем можем через него что угодно и как угодно установить.
Но вся красота моего метода в том, что мы можем его использовать основываясь на стандартных компонентах и сохраняя преимущества обновлений.
Или нам требуется установить картинку раздела из компонента. Допустим на сайте есть внутренний вижуал, который меняется в зависимости от выбранного автомобиля. Пример
Иван, пользовался первым вариантом вашего суперкомпонента и теперь для новых идей нужна именно новая версия вашей разработки. Спасибо огромное за компонент! Но все же у меня появился вопрос и я был бы рад услышать ответ. Итак, у меня компонент необходимо частично кешировать, обычный код я вставил в result_modifier.php, а код, который компоненту не нужно кешировать и который добавляет к массиву arResult элементом еще один массив в result_modifier_nc.php - в принципе работает, но не так как хотелось бы. Шаблон обрабатывает код до result_modifier_nc.php и соответственно не видит добавленный в result_modifier_nc.php элемент результирующего массива... Как сделать чтобы шаблон подключался после result_modifier_nc.php? Или может я что то не так делаю ))
Да, в текущей реализации супер-компонента файл result_modifier_nc.php подключается уже после шаблона. Боюсь что переделать компонент чтобы файл result_modifier_nc.php подключался после result_modifier.php и перед файлом template.php без модификации ядра не получится, так как компонент использует стандартную функцию
$this->StartResultCache();
которая, если компонент закеширован, сразу возвратит html код.
Думаю, для такого случая как Вам нужен нужно либо написать свой компонент (что, впринципе, не так уж и сложно), либо если нужно обходиться только супер компонентом - то поставть на странице 2 супер компонента, один из которых будет кешироваться, а второй кешироваться не будет. Для удобства их можно заключить в один комплексный супер-компонент, чтобы в виз. редакторе на странице была только одна иконка компонента.
Я тоже столкнулся с тем, что нужно использовать частичное кеширование. Но не настолько я пока "могуч" в этом вопросе, что подумал, а если для вывода использовать template_nc.php куда можно получать и кешируемый $arResult с result_modifier.php и также не кешируемый с result_modifier_nc.php. Это ускорит вывод данных по сравнению с просто компонентом у которого отключено кеширование?
Очень часто в целях поисковой оптимизации требуется установить особенный заголовок
Т.е., если я хочу при выводе Элемента инфоблока, на основе содержимого элемента установить свой заголовок мне нужно: 1. в result_modifier.php сделать {$component->arResult["ELEMENTS"]["myproperty"]='заголовок+значение_свойства'} 2. а на индексной странице, где вызывается компонент, добавить $myresult перед вызовом компонента и после присвоить свойство страницы или папки, которое потом в можно будет использовать в шаблоне сайта?
component_epilog.php тоже спасает не от всего. Например что делать если в catalog.section нужно показать какие товары в корзине и какие нет? На форуме все делают через javascript который будет написан в component_epilog.php. То есть на мой взгляд это обратный костыль. Сервер знает какие товары лежат в корзине, но показать не может, и эта задача падает на сторону клиента.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».