На одной из страниц нашего сайта применены сразу три разных способа, чтобы сделать некэшируемые области в стандартном компоненте.[spoiler]
Лирическое отступление:
Что такое HTML кэширование в стандартных компонентах?
Это, когда всё, что выводится в шаблоне компонента, временно сохраняется в файле. И пока время кэширования не истечёт, что-либо изменить невозможно: ни в файле template.php, ни в result_modifier.php. Эти файлы просто не вызываются.
Простейший пример, когда нужна некэшируемая область:
Надо отобразить кнопку «В корзину», но если товар уже добавлен, то писать «Товар в корзине».
Исправить можно только одним способом: необходимо парсить. Надо получить HTML компонента и в него вставить то, что нам надо.
В девятой версии Битрикса появился волшебный файлик component_epilog.php, а Евгений Лазарчик объяснил, как его можно использовать для такой задачи.
Но поскольку каталог на geodom.ru сделан до выхода девятой версии, парсить пришлось по-другому.
На странице товара на сайте geodom.ru сделаны некэшируемые области тремя способами:
Способ 1:
кнопка добавить в корзину / товар в корзине,
голосовалка «звёздочки»,
голосовалка «рука».
Способ 2:
отзывы о товаре с листалкой и сортировками. (news.list впихнут в catalog.element).
Способ 3:
ссылка подписаться / отписаться,
ссылка отложить / товар отложен.
Замечение. Голосовалка «рука» вставлена в отзыв о товаре (news.list), а значит последовательно применились способ 2 и 1.
На картинке отмечены некэшируемые области и способы, которыми они сделаны.
Как это выглядит:
Найдите 5 отличий:
Сначала.
После изменения некэшируемых областей.
Способ 1.
Самый универсальный способ по-битриксовски. Очень удобен, когда одну и ту же подстановку надо делать на разных страницах.
Обработка события OnEndBufferContent. Парсим код всей страницы.
В файле init.php:
AddEventHandler("main", "OnEndBufferContent", "ChangeMyContent");
function ChangeMyContent($content)
{
// только если на странице есть нужный шаблон куда подставлять
if (strpos( $content, '<ШАБЛОН>')!== false ) {
ob_start();
// здесь вызываются компоненты которые надо подставить.
$out1 = trim(ob_get_contents());
ob_end_clean();
$out1 = str_replace('<ШАБЛОН>', $out1, $content);
}
}
Замечание. <ШАБЛОН> лучше всего писать со спецсимволами <>.
Начинающие хакеры не испортят вид вашей страницы, написав что-то в отзыве о товаре.
Cпособ 2.1.
Примерно тоже самое, но пишем в коде страницы, на которой лежат компоненты:
ob_start();
// код компонента, куда вставляем.
$out1 = trim(ob_get_contents());
ob_end_clean();
if (strlen($out1)>0) {
if ( strpos( $out1, '<ШАБЛОН>')!== false ) {
ob_start();
// код, что вставляем.
$out2 = trim(ob_get_contents());
ob_end_clean();
echo str_replace('<ШАБЛОН>', $out2, $out1);
} else {
echo $out1;
}
}
Способ 2.2.
Чуть хитрее. Применяется, когда во вставляемом компоненте включен аякс.
Мы не вставляем один компонент в другой. А наоборот. Первый компонент режем и половинки вставляем вокруг второго.
ob_start();
// код компонента, куда вставляем.
$out1 = trim(ob_get_contents());
ob_end_clean();
if (strlen($out1)>0) {
if ( strpos( $out1, '<ШАБЛОН>')!== false ) {
$parts = explode('<ШАБЛОН>', $out1);
echo $parts[0];
// код, что вставляем.
echo $parts[1];
} else {
echo $out1;
}
}
Способ 3.
Самый любимый. В одну строчку.
А зачем парсить на сервере и тратить дорогие ресурсы? Пусть у пользователя JavaScript сам подставляет.
Оказалось, что такая реализация самая универсальная и совсем не сложная.
<!--Скрытый див, где-то на странице.-->
<div style="display: none;" id="from">Наш html, который надо подставить</div>
...
<!--пустой див в закэшированном компонете-->
<div style="display: block;" id="to"></div>
<script type="text/JavaScript">
<!--Вот эта строчка-->
document.getElementById('to').innerHTML = document.getElementById('from').innerHTML;
</script>
Мы всегда можем найти нужный узел по id и вставить в него тот HTML который нам нравится.
С точки зрения быстродействия, безопасности и простоты реализации во многих случаях третий способ — самый лучший выбор.
Я о белом сео. Если, например, разместить страницу с помощью какой-нибудь семантической разметки, то гугл не отобразит размеченный сниппет в результатах поиска, если на странице будут присутствовать скрытые элементы. Где-то в справке было написано.
В способе 3 style="display:none;" - действительно слишком грубо выглядит. Можете сделать какой-нибудь класс, где left: -10000px;. Никакой робот не догадается, что вы кусок контента спрятали.
Потом вы перенесете этот кусок в нужную область на JavaScript. Если живой человек придет на страницу и увидит этот спрятанный контент, значит он не спрятанный. Это белое СЕО, мы никого не обманываем.
Способом 3 через Javascript удобно отрисовывать какие-нибудь формы, кнопки или голосовалки, которые гуглу не очень нужны.
Зато, если хотите соблюсти все формальности, можете подставлять способом 1 или 2. Или модулем Включаемый код.
Да, почитал еще раз, скрытые элементы не должны касаться размеченного содержания, т.е. внутри скрытого блока не должно быть элементов семантической разметки, а так, возможно, ваш способ хорош, я отрисовал шаблон в эпилоге, а закэшировал только работу компонента, т.к. мне нужно было именно это. В любьом случае спасибо за вашу работу, думаю, она будет полезной кому-нибудь.
Зайцев Артемий, всегда думал что коммерческая CMS такого уровня должна предоставлять это из коробки. такие элементарные вещи уже решены даже в беслпатных системах
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».