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 [15240 просмотров]