Показываем 404 страницу

Компоненты Bitix, в случае, если требуемый элемент/раздел не найден не показывают страницу с 404 ошибкой. Они просто выводят текст ошибки и возвращают статус 404:

Элемент не найден!

Я считаю что это никуда не годится. Юзабилити тут даже и не пахнет. А как же показать пользователю стилизованную страницу, на которой направить пользователя на нужные страницы?

Благо делается это совсем просто, достаточно подготовить файл 404.php, который нужно разместить в корне. Это у вас скорее всего уже сделано, т.к. по умолчанию в .htaccess bitix'а указано что, если в структуре сайта запрашиваемый файл не найден - то возвращать /404.php

Далее в файле 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';
    }
}

Событие вызывается в момент когда страница уже сформировалась. Происходит проверка на ERROR_404 == "Y". Если проверка успешна, значит какой то из компонентов на странице вернул 404-ю ошибку. Очищаем буфер вывода $APPLICATION->RestartBuffer(); и подключаем визуальные файлы для отображения подготовленной 404 страницы.

Текст в компоненте

На случай написания своего компонента, приведу код, который нужно вызывать в компоненте при обнаружении 404-й ошибки:


if (!isset($arResult['SECTION'])){
    $this->AbortResultCache();
    @define('ERROR_404', 'Y');
    return;
}

Если искомый результат не найден, прерываем кеширование компонента, объявляем ERROR_404, выходим из компонента.

Типовой файл 404.php

Файл 404.php все же не совсем обычная страница, поэтому приведу заготовку:


<?require($_SERVER['DOCUMENT_ROOT'].'/bitrix/header.php');
CHTTP::SetStatus('404 Not Found');
@define('ERROR_404','Y');
$APPLICATION->SetTitle('Страница не найдена');?>
404
<?require($_SERVER['DOCUMENT_ROOT'].'/bitrix/footer.php');?>

Устанавливаем статус 404, объявляем ERROR_404(вдруг обратились напрямую к /404.php). В остальном это обычная текстовая страница bitrix.

Послесловие

Мне этот метод не нравится. Проблема в том, что после обнаружения 404-ошибки страница продолжает отрабатывать до конца, а затем этот напрасный труд очищается.

Как то на коленке я пробовал найти другое решение, проверил то, что пришло в голову, но не вышло, потом я на это забил. Возможно если подойти к вопросу обстоятельно то окажется что все просто и решение на поверхности, но пока как то не до этого. Да и кто смотрит на 404-ю?!

Если у вас есть более элегантное и менее ресурсозатратное решение - прошу в комментарии.

Комментарии:

Дима

16.03.2015 11:17:59

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

Я использовал следующее решение:
1. создал в корне сайта файл выводимый файл - 404.php.
2. создал файл init.php (в /bitrix/php_interface/) и вставил в него следующий код:

<?
AddEventHandler('main', 'OnEpilog', '_Check404Error', 1);
function _Check404Error(){
if(defined('ERROR_404') && ERROR_404=='Y' || CHTTP::GetLastStatus() == "404 Not Found"){
CHTTP::SetStatus('404 Not Found');
GLOBAL $APPLICATION;
$APPLICATION->RestartBuffer();
require $_SERVER['DOCUMENT_ROOT'].'/404.php';
}
}
?>

И все! Если кому понадобиться на здоровье!

Lumenq

12.06.2015 14:20:45

данная структура у меня работать не хотела. помогла небольшая переделачка

AddEventHandler('main', 'OnEpilog', '_Check404Error', 1);
function _Check404Error(){
if (CHTTP::GetLastStatus() == "404 Not Found"){
GLOBAL $APPLICATION;
$APPLICATION->RestartBuffer();
require ($_SERVER['DOCUMENT_ROOT'].'/404.php');
}}

Joseph

06.07.2015 16:48:15

Автор, Вы молодец!

Виктор

19.08.2015 15:18:10

Как избавиться от срабатывания на главной?

Андрей

25.10.2017 13:55:11

"код, который нужно вызывать в компоненте при обнаружении 404-й ошибки"
Не могли бы Вы поподробнее указать в каком месте component.php это можно добавить. Проблема насущная, а нагуглить еще варианты по этой теме не удалось, только у Вас об этом.

Максим

25.10.2017 16:32:48

Андрей, стандартные компоненты сами так делают, у них есть в настройках галочка чтото вроде показывать 404. Но при нажатии этой галочки http статус страницы становится 404, но оформленная страница не выводится.
Итак, при использовании стандартных компонент, нужно только добавить код в init.php, и создать саму страницу 404, файл в корне 404.php.

Если же компонент у вас свой, но в нем в момент когда вы понимаете, что нужно показать ошибку 404 нужно

$this->AbortResultCache(); //Прервать кеширование компонента - если оно используется в вашем компоненте
@define('ERROR_404', 'Y');//Объявить константу (это основное условия показа 404 страницы)
return;//Выйти из компонента

Оставить комментарий:

Представьтесь пожалуйста:
Электронная почта:
Электронный адрес не публикуются
Текст сообщения:
Для подсветки кода, оборачивайте ваш код в теги <code></code>
Введите 5 цифр с картинки:

Рекомендую:

Поддержать проект:

бесполезная кнопка, которую еще никто не нажал:)
Нажали! Кнопку нажали уже 7 человек!!! Спасибо, очень мотивирует!