+7 495 008 8452 пн.-пт. 10:00 – 17:00
Если у вас возникли какие либо вопросы которые вы не смогли решить по нашим публикациям самостоятельно,
то ждем ваше обращение в нашей службе тех поддержки.


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 = ($_SERVER["SCRIPT_NAME"] == "/index.php" ? true : false);
define("PATH_TO_404", "/404.php");
?>
...
<!DOCTYPE html>

Кстати, переменная $bIndexPage может сослужить полезную службу при выводе шаблона с различными наборами компонентов на главной и внутренних страницах при единообразии прочего содержимого и стилей.

Назад в раздел

Подписаться на новые материалы раздела:












CAPTCHA