Хочу сохранить
статью уважаемого
Бакирова Марата, который очень помог наладить индексацию сайта!
Bitrix и ошибка 404
Давно бились над проблемой с SEO и применением стандартных комплексных компонентов (bitrix:news, bitrix.catalog) при использовании ЧПУ.
Проблема заключалась вот в чем: при отдаче страницы с отсутствующим элементом или секцией инфоблока выставляется статус "404 Not Found" (в теле компонентов bitrix:news.list, bitrix:news.detail, bitrix:catalog.section, bitrix:catalog.element есть соответствующие строки, но к сожалению не было способа показать тело 404-ой страницы (мы обычно создаем страницу /404.php) с ее оформлением и пр.
Поначалу нас устраивал редирект на эту страницу вида:
LocalRedirect("/404.php", "404 Not Found");
но чтобы им воспользоваться приходилось создавать дубликаты компонентов в своем пространстве имен (anima:catalog.section, например).
Потом было найдено более изящное решение, не задевающее компоненты. В стандартных компонентах используется определение константы ERROR_404 в случае проблем с поиском инфоблока, секии, элемента во время выполнения компонента, но по заверениям разработчиков она используется исключительно для статистики. Однако, отображение стрницы - единый runtime и определенные константы можно использовать практически в самом его (runtime-a) конце. Результатом этих роазмышлений стал код в init.php:
/* Неочевидное перенаправление на страницу 404-ой ошибки */
AddEventHandler("main", "OnEpilog", "Redirect404");
function Redirect404() {
if(defined("ERROR_404") ) {
LocalRedirect("/404.php", "404 Not Found");
}
}
Довольно легко для понимания и универсально и работает везде, но... У данной конструкции (у редиректа) естьи темные стороны.
Пользователь сайта, случайно вбив ошибочный длинный URL перебрасывался на /404.php без возможности увидеть и исправить ошибку в строке адреса.
Поисковой робот, придя на ошибочную страницу видел странную последовательность: при обращении к несуществующей странице он получал статус 301 Moved Permanently (в редких случаях "404 Not found";) и переадресацию на страницу /404.php, которая выставляла статус "404 Not found". Немного путано.
Тогда появилась идея: в функции Redirect404() очистить буфер вывода с помощью $APPLICATION->RestartBuffer(); и "заинклюдить" /404.php. Но тут на словах оказалось проще, чем на деле. Беда крылась в том, что пролог и эпилог сайта вызываются через конструкцию require_once и повторно вызвать их (для отображения шапки, футера, стилей на заветной 404-ой странице) оказалось невозможно; другими словами мы теряли, к примеру, меню, вставленное в визуальную часть пролога (header.php шаблона).
Путем экспериментов, проб и ошибок мы пришли к довольно универсальной записи:
AddEventHandler("main", "OnEpilog", "Redirect404");
function Redirect404() {
if(
!defined('ADMIN_SECTION') &&
defined("ERROR_404") &&
defined("PATH_TO_404") &&
file_exists($_SERVER["DOCUMENT_ROOT"].PATH_TO_404)
) {
//LocalRedirect("/404.php", "404 Not Found");
global $APPLICATION;
$APPLICATION->RestartBuffer();
CHTTP::SetStatus("404 Not Found");
include($_SERVER["DOCUMENT_ROOT"].SITE_TEMPLATE_PATH."/header.php");
include($_SERVER["DOCUMENT_ROOT"].PATH_TO_404);
include($_SERVER["DOCUMENT_ROOT"].SITE_TEMPLATE_PATH."/footer.php");
}
}
Внимательный зритель заметит, что в функции появилась константа PATH_TO_404. Определять данную константу предлагается первой строкой в визуальной части пролога:
...
Кстати, переменная $bIndexPage может сослужить полезную службу при выводе шаблона с различными наборами компонентов на главной и внутренних страницах при единообразии прочего содержимого и стилей.