Обработка ошибок с помощью trigger_error() и set_e

случае, когда сообщение об ошибке должно попасть в log-файл и быть отправлено на e-mail администратору (например - ошибка при выполнении SQL запроса, или отсутствии парв доступа к необходимому файлу). Ошибки уровня E_USER_NOTICE будут вызываться при возникновении "лёгких" ошибок (например - пользователь некорректно заполнил форму, или запросил из базы несуществующую запись).

Теперь наша функция обработки ошибок будет выглядеть примерно так:

// Немного предварительных настроек

// устанавливаем режим отображения ошибок
// отображать все ошибки, кроме E_NOTICE
error_reporting (E_ALL & ~E_NOTICE);

// эта константа отвечает за
// включение/выключение режима отладки
// во время отладки - сообщения не отсылаются
// по почте, а просто печатаются на экран
define('DEBUG', 0);

// это глобальная переменная, в которой
// будет храниться сообщение, которое
// должен видеть пользователь
$MSG = '';

// e-mail разработчика, куда отправлять ошибки
define('ADM_EMAIL','admin@example.com');

// log-файл
define('LOGFILE','/home/mysite/mylog.log');

// разница во времени с сервером (в секундах)
define('TIMEOFFSET', 0);

// сама функция

function my_error_handler($code, $msg, $file, $line)
{
// глобальная переменная, в которую будет
// записываться сообщение об ошибке.
global $MSG;

// пропускаем ошибки уровня E_NOTICE
// и игнорируем ошибки, если режим сообщения об ошибках отключен
if ( ($code == E_NOTICE) or (error_reporting() == 0) ) {
return;
}

// если мы вызвали ошибку уровня E_USER_NOTICE - просто
// записать текст ошибки в глобальную переменную $MSG
// и прекратить выполнение функции

if ($code == E_USER_NOTICE) {
$MSG = $msg;
Return;
}

// если ошибка уровня E_ERROR - печатаем текст ошибки
// и завершаем выполнение скрипта

if ($code == E_ERROR) {
die ('<br><b>ERROR:</b> '.$msg.'<br>In '.$file.' (line '.$line.')<br>');
}

// если ошибка уровня E_WARNING - печатаем текст ошибки
// и прекращаем выполнение функции

if ($code == E_WARNING) {
echo '<br><b>WARNING:</b> '.$msg.'<br>In '.$file.' (line '.$line.')<br>';
Return;
}

// если ошибка уровня E_USER_ERROR

if ($code == E_USER_ERROR) {

// записываем в переменную $MSG текст, о том что произошла ошибка,
// причины сообщать не будем, только сообщим что подробности
// отправлены на e-mail кому следует.

$MSG = 'Критическая Ошибка: действие выполнено небыло. <br>

Сообщение об ошибке было отправлено разработчику.';

// подробности записываем в переменную $text

$text = $msg.'<br>'.'Файл: '.$file.' ('.$line.')';

// Если константа DEBUG установлена в 1 - печатаем информацию об
// ошибке на экран, если нет - отправляем текст ошибки почтой
// функция error_mail() и пишем в log - функция error_writelog()

if (DEBUG == 1) {
error_print($text);
} else {
error_mail($text);
error_writelog($text);
}

Return;
}
}


// устанавливаем обработчик
set_error_handler('my_error_handler');

Теперь описываем служебные функции
// ф-я печатает ошибку на экран
function error_print($text)
{
echo $text.'<p>';
}

// ф-я отправляет ошибку почтой
function error_mail($text)
{
$text = str_replace("<br>", "\\n", $text);

$info = 'Время: '.get_datetime()."\\nRemote IP:".get_ip()."\\n";

mail(ADM_EMAIL, "Error reporting", $info.$text);
}

// ф-я пишет ошибку в лог
function error_writelog($text)
{
$text = str_replace("<br>", "\\t", $text);
if (@$fh = fopen(LOGFILE, "a+")) {
fputs($fh, get_datetime()."\\t".get_ip()."\\t".$text."\\n");
fclose($fh);
}
}


// получаем время, с учётом разницы во времени
function get_time()
{
return(date("H:i", time () + TIMEOFFSET));
}

// получаем дату, с учётом разницы во времени
function get_date()
{
return(date("Y-m-d", time () + TIMEOFFSET));
}

// получаем дату и время, с учётом разницы во времени
function get_datetime()
{
return get_date().' '.get_time();
}

// получаем IP
function get_ip()
{
return($_SERVER['REMOTE_ADDR']);
}
И наконец пример использования
// ф-я записывает новость в файл
function write_news($title, $text)
{
$news_file = '/home/mysite/news.txt';

// проверяем наличие заголовка - ошибка не критическая
if (!trim($title)) {

// для того чтобы определить что функция завершилась
// неудачей - необходимо вернуть false. Функция
// trigger_error() - возвращает true, мы будем
// возвращать её инвертированный результат

return !trigger_error('Необходимо указать заголовок новости');
}

// проверяем наличие текста новости - ошибка не критическая
if (!trim($text)) {
return !trigger_error('Необходимо указать текст новости');
}

// проверяем наличие файла в который будем писать
// если файл не найден - возникает критическая ошибка

if (!file_exists($news_file)) {
return !trigger_error('Файл базы новостей не найден!', E_USER_ERROR);
}

// ...тут предварительная обработка данных...

// записываем новость
$fh = fopen($news_file, "a+");
fputs($fh, $title."\\t".$text."\\n");
fclose($fh);

// если всё нормально - функция возвращает true
return true;
}

// пытаемся записать новость
// эти данные могут приходить из web-формы

$res = write_news("Моя новость", "Текст моей новости");

if ($res === false) {

// если вернулся false - печатаем ошибку
echo $MSG;

} else {

// если всё в порядке - можно сообщить об этом
// а лучше отфорвардить пользователя куда-нибудь.
echo 'Новость была добавлена';
}

Для того чтобы пример заработал - просто скопируйте в PHP-файл три предыдущих блока кода. Не забудьте установить права доступа на log-файл 777 для того чтобы скрипт мог с ним работать, прописать правильные пути и указать свой e-mail. Вы можете включить режим отладки установкой переменной DEBUG в 1.
Скачать файл txt fb2