В битриксе 404 ошибка отрабатывается весьма специфически: неправильный адрес со статических страниц и разделов корректно перебрасывает на страницу 404.php, при этом, сохраняя неправильный URL в адресной строке браузера. То есть, все по SEO.
А вот если неправильный адрес начинается с раздела инфоблока или каталога, то сервер отдаст браузеру 404 статус страницы (и то, при определенных настройках инфоблока, о которых ниже), но 404 страницу не покажет, а покажет корневую страницу инфоблока, причем, иногда совсем другого инфоблока. Но, все-таки, сохранит неправильный URL в адресной строке.
В интернете данный вопрос поднимался не раз. Когда-то популярным решением была настройка в битрикс принудительного редиректа на 404 страницу.))) Перечитав изрядно статей, выполнив несколько найденных инструкций, желаемого результата добиться не удалось(((. Пришлось, вооружившись командой print backtrace, отловить негодяйскую 404 ошибку и заставить ее работать, как положено.
Ставим задачу:
- Нужно, чтобы инфоблоки и каталоги в случае неправильной ссылки отдавали 404 статус.
- Нужно, чтобы этот статус правильно обрабатывался и приводил к вызову страницы 404.php.
На что стоит обратить внимание?
- Файл 404.php лежит в корне сайта. Должен выглядеть вот так (тут все стандартно):
<? if ($_SERVER['DOCUMENT_URI'] == "/404.php") { $_SERVER['REQUEST_URI'] = $_SERVER['DOCUMENT_URI']; } include_once($_SERVER['DOCUMENT_ROOT'].'/bitrix/modules/main/include/urlrewrite.php'); CHTTP::SetStatus('404 Not Found'); @define('ERROR_404', 'Y'); require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php"); $APPLICATION->SetTitle("Страница не найдена"); ?> ТУТ ТЕКСТ ВСЯКИЙ <? require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php"); ?>
- В .htaccess должна быть вот такая строчка:
ErrorDocument 404 /404.php
Если у вас сервер на nginx, то нужно прописать в конфиге, в секции location, следующее:
error_page 404 = /404.php;
Тех. отступление:
Попробуем симулировать 404 ошибку с какой-нибудь статической страницы и отловить результат через команду debug_print_backtrace();
Смотрим файл, видим там строку с инклюдом 404 страницы. Она вызывается, очевидно, в том случае, если страница не найдена в структуре файлов и папок, а также в файле urlrewrite.php в корне сайта, где как раз описаны все наши инфоблоки и каталоги (для правильной работы ЧПУ).
Первая поставленная нами задача выполняется настройкой инфоблоков и компонентов.
- Проверим настройки самих каталогов:
URL страницы ИБ — должен указывать на папку, из которой будет осуществляться вызов инфоблока.
URL страницы раздела — если структура инфоблока будет иметь подразделы, то ссылка должна строиться на основе символьного кода раздела.
URL страницы детального просмотра — если элемент находится в подразделе, то к ссылке будет прибавляться символьный код раздела перед символьным кодом элемента. Иначе — только символьный код элемента.
- И инфоблоков:
То есть, как мы видим, для инфоблоков подразделы можно не описывать.
- Проверяем настройки вызова инфоблоков:
Обязательно проверяем, что отмечена галка «Включить поддержку ЧПУ»!
Каталог ЧПУ — корневая папка инфоблока.
Раздел — #SECTION_CODE#/ — повторяем из настроек инфоблока, но не ставим слеш в начале, иначе компонент будет работать неверно.
Детальная информация — #SECTION_CODE#/#ELEMENT_CODE#/ — ссылка формируется на основе символьного кода раздела (если есть) и кода элемента. Опять же, слеш в начале не ставим!
Если предполагается, что все элементы будут располагаться в корне инфоблока, без подразделов, то можно использовать следующие настройки:
То есть, поле для страницы раздела вообще можем пропустить, для страницы элемента: #ELEMENT_CODE#/ . Не забываем пропустить слеш в начале!
- Отмечаем галочку там же в настройках: «Устанавливать статус 404, если не найдены элемент или раздел:».
Тех. отступление:
После сохранения всех настроек, если мы набираем в разделе инфоблока неправильный адрес, то по-прежнему вместо 404 страницы увидим корневую страницу раздела инфоблока, но страница будет иметь в заголовке 404 статус. Посмотреть его можно через браузерную панель разработчика:
Этим мы и воспользуемся, а чтобы данный статус правильно обрабатывался
- Добавим следующий код в файл /bitrix/php_interface/init.php:
<? AddEventHandler('main', 'OnEpilog', '_Check404Error', 1); function _Check404Error(){ if (defined('ERROR_404') && ERROR_404 == 'Y') { global $APPLICATION; $APPLICATION->RestartBuffer(); include $_SERVER['DOCUMENT_ROOT'] . SITE_TEMPLATE_PATH . '/header.php'; include $_SERVER['DOCUMENT_ROOT'] . '/404.php'; include $_SERVER['DOCUMENT_ROOT'] . SITE_TEMPLATE_PATH . '/footer.php'; } } ?>
С этого момента страница ошибок будет работать! (наверное))) Если нет, опишите вашу ситуацию в комментариях.
UPD от 29.08.15: чуть обновил код файла 404.php и сниппет для init.php.
UPD от 15.01.18: настраивал сегодня на одном проекте отладку 404-й ошибки по данной инструкции. Все работает отлично)) Версия битрикса — последняя на указанную дату.