БлогNot. PHP: пишем собственную страницу обработки ошибок Apache (404 и др.)

PHP: пишем собственную страницу обработки ошибок Apache (404 и др.)

У нормального хостера проблема решается очень легко: достаточно написать свой файл .htaccess и положить его в корневую папку сайта.

Синтаксис нужной нам директивы:

ErrorDocument код-ошибки документ

Примеры:

ErrorDocument 403 /error.html
ErrorDocument 404 /bad_urls.php
ErrorDocument 500 http://my.server.com/cgi-bin/error

Тремя показанными ошибками, как самыми частыми, и ограничимся. Добавив к файлу .htaccess директивы, на всякий случай отключающие устаревшие "волшебные кавычки" и явно указывающие кодировку сайта (у нас русскоязычная windows), получим вот что:

AddDefaultCharset windows-1251 
php_flag magic_quotes_gpc off
php_flag magic_quotes_runtime off
php_flag magic_quotes_sybase off
ErrorDocument 403 /error.php?e=403
ErrorDocument 404 /error.php?e=404
ErrorDocument 500 /error.php?e=500
Проблемы с созданием файла под именем .htaccess?
Пользуйтесь не проводничком и блокнотиком, а нормальным файл-менеджером, например, Far
Пока не умеете с ним работать (там есть и отличные плагины FTP/SFTP для закачки файлов на сайты), нет смысла работать и с хостами :)

Имейте в виду, что если вы напишете в директиве ErrorDocument полный адрес скрипта обработки ошибок вида http://my.server.com/error.php?e=404 вместо /error.php?e=404, то будет редирект 302 на указанный URL вместо корректной обработки ошибки 404. Ну и неправильный юзвериный адрес исчезнет из адресной строки браузера :)

Но! При указании относительного адреса обработчика error.php ссылки, выданные на страницу обработчика как относительные (то есть, <a href="my.php">link<a> или <a href="/my.php">link<a>, будут восприниматься скриптом как адреса от неправильного URL. Правильно в этом случае выдавать <a href="http://my.server.com/my.php">link<a> (где my.server.com - имя вашего сервера), а эту самую my.server.com получать из настроек сайта.

Саму обработку для удобства сделаем одним файлом error.php - не писать же кучу отдельных документов? Наш обработчик будет параметром получать номер ошибки. Файл error.php, как видно из директивы ErrorDocument, нужно также скопировать в корневую папку сайта.

Вот пример кода такого обработчика ошибок сервера:

<?php 
require_once ("functions.php");

$id=get_int('e');
if (empty($e)) { redirect (); }
title ("Ошибка $e");
include "header.php";
$emsgs = array (
 403 => 'Сервер не отвечает', 404 => 'Документ не найден', 500 => 'Внутренняя ошибка сервера'
);
$emsg = 'Описание ошибки не найдено';
if (array_key_exists($e, $search_array)) $emsg = $emsgs[$e];
echo '
 <p>Что-то пошло не так... Сервер вернул код ошибки '.$e.' ('.$emsg.')
 <p>Инфа для пользователя и ссылки, куда податься, обычный HTML
';
if (isset ($_SERVER['REQUEST_URI']))
 echo '<p>Вы пытались перейти на адрес : '.request_url().'</p>';
if (isset ($_SERVER['HTTP_REFERER']))
 echo '<p>Вы пришли с адреса: '.$_SERVER['HTTP_REFERER'].'</p>';
include "footer.php";
?>

Здесь

require_once ("functions.php");

подключает гипотетическую библиотеку функций сайта, нам, в общем-то, для примера достаточно трёх.

1. Функция redirect просто отправляет юзера туда, откуда он пришёл (на случай, если сам error.php вызван напрямую и без обязательного параметра):

function redirect () {
 if (isset ($_SERVER['HTTP_REFERER'])) {
  header('Location: '.$_SERVER['HTTP_REFERER']);
 }
 else {
  header('Location: index.php');
 }
}

2. Функция get_int возвращает целое число, полученное из параметра URL-адреса $_GET с именем $name или пустую строку, если допустимое число не передано. Функция может выглядеть, например, так:

function get_int($name) {
 $var='';
 if (isset($_GET[$name])) $var = 0 + intval(htmlspecialchars(trim($_GET[$name])));
 return $var;
}

3. Функция title сохраняет переданную ей величину в статической переменной, скажем,

 function title ($str) { 
  static $title='';
  if (!empty($str)) $title=$str;
  return $title;
 }

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

<title><?php echo title(''); ?></title>

(код может быть помещён в файл header.php - стандартную "шапку" всех страниц сайта). Так что, директивы

include "header.php";
include "footer.php";

как раз подключают стандартные "шапку" и "подвал" сайта.

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

Ах, да, часто в качестве ссылки на текущий адрес лепят просто $_SERVER['REQUEST_URI'], забывая, что это

имя скрипта, начиная от корневой директории виртуального хоста

но никак не полный путь.

Функция request_url как раз и пытается грамотно получить на PHP текущий полный URL-адрес страницы, с учётом того, что соединение может быть не по 80 порту и не по http, а по https. Вот эта волшебная функция, считаем, что она там же, в functions.php:

function request_url() {
 $result = '';
 $port = 80;
 if (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS']=='on')) {
  $result .= 'https://';
  $port = 443;
 } 
 else $result .= 'http://';
 $result .= $_SERVER['SERVER_NAME'];
 if ($_SERVER['SERVER_PORT'] != $port) $result .= ':'.$_SERVER['SERVER_PORT'];
 return $result.$_SERVER['REQUEST_URI'];
}

Что у нас вышло можно увидеть, например, щёлкнув по этой несуществующей ссылке на страницу моего блога.

19.02.2015, 14:50 [14962 просмотра]


теги: html ошибка php сервер

К этой статье пока нет комментариев, Ваш будет первым