Скрываем вывод ошибок в php

inet security Скрываем вывод ошибок в php Ошибки в процессе выполнения скрипта бывают не то, чтобы часто, но все-таки иногда. Ведь все предусмотреть невозможно и бывают участки в коде, которые работают неправильно. Чтобы нам, программерам, понять, почему произошла та или иная ошибка, php выводит ее описание и даже говорит, где она произошла (в каком скрипте и на какой строчке). Но лучше их на экран не выводить, чтобы лишним глазам не было дополнительной информации о структуре и т.п. нашего сайта, иначе в нем будет легче найти уязвимость.

Вот пример:

Warning: fopen(test) [function.fopen]: failed to open stream: No such file or directory in D:\MyDocs\My Works\Development\PHP\test\test.php on line 2

Так нам PHP сказал, что мы пытаемся открыть файл с именем test, которого не существует. Также, как видите, он сказал, что это произошло в файле test.php на строке 2.

Ловим сообщения об ошибках

Итак, если мы не хотим выводить ошибки в окно браузера, нам надо этот вывод отключить или перенаправить. Отключается вывод ошибок одной строчкой, прописанной в .htaccess:

php_flag display_errors off

Но это не дело, т.к. ошибки мы, как разработчики своей системы, должны, обязаны видеть, чтобы устранить неисправность в каком-нибудь скрипте. Поэтому просто отключить вывод ошибок было бы равнозначно тому, что мы закрываем глаза на какую-то болезнь в нашем организме. А болезнь, как известно не проходит, если про нее просто забыть. Поэтому нам нужно перенаправить вывод ошибок в файл. Об этом и пойдет речь далее.

Ну, во-первых, нам нужно включить вывод ошибок в .htaccess, иначе мы их вообще не увидим (ни наши посетители, ни мы сами):

php_flag display_errors on

Потом нам нужно определиться с файлом, в который мы будем выводить эти ошибки. Пусть это будет файл errors.log в корневой директории нашего сайта. А затем, нам нужно перехватить все ошибки, чтобы перенаправить их вывод в файл errors.log.

Это делается с помощью функции set_error_handler. Она позволяет задать глобальную функцию-обработчик всех ошибок. Покажу сразу на примере, как это делается:

<?
function err_handler($errno, $errmsg, $filename, $linenum) {

    if (!in_array($errno, Array(E_NOTICE, E_STRICT, E_WARNING))) {
   
        $date = date('Y-m-d H:i:s (T)');
   
        $f = fopen('errors.log', 'a');
       
        if (!empty($f)) {
       
            $err  = "<error>\r\n";
            $err .= "  <date>$date</date>\r\n";
            $err .= "  <errno>$errno</errno>\r\n";
            $err .= "  <errmsg>$errmsg</errmsg>\r\n";
            $err .= "  <filename>$filename</filename>\r\n";
            $err .= "  <linenum>$linenum</linenum>\r\n";
            $err .= "</error>\r\n";
            fwrite($f, $err);
            fclose($f);
           
        }
       
    }

}

set_error_handler('err_handler');

?>

Здесь предполагается, что скрипт, в котором мы прописали данный вызов, находится в одной директории с файлом errors.log. Естественно, вызов set_error_handler нужно поставить в самое начало нашего скрипта.

Приведенный обработчик принимает следующие параметры:
$errno – номер ошибки (ее тип);
$errmsg – текстовое сообщение об ошибке, которое несет в себе весь смысл;
$filename – полный путь к файлу, в котором произошла ошибка;
$linenum – номер строки в файле.

Условием

if (!in_array($errno, Array(E_NOTICE, E_STRICT, E_WARNING)))

я отсек неважные сообщения типов E_NOTICE, E_STRICT, E_WARNING, которые только засоряли бы лог-файл errors.log:

E_NOTICE – означает, что интерпретатор заметил что-то, что может быть ошибкой, но не обязательно ошибка;
E_STRICT – предупреждение, что какой-то участок кода может быть обратно несовместим с предыдущими версиями PHP;
E_WARNING – предупреждение, после которого скрипт продолжает свое выполнение.

Потом при возникновении каждой ошибки я открываю файл errors.log для добавления туда информации в следующем формате (для удобства ее просмотра):


Дата и время возникновения ошибки
Номер типа ошибки
Сообщение
Путь к файлу, в котором произошла ошибка

Номер строки в файле с ошибкой

При всем этом посетитель сайта не видит ошибок, как будто их нет. А мы – разработчики – можем их просмотреть в своем файле лога.

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

flock($f, LOCK_EX);
fwrite($f, $err);
flock($f, LOCK_UN);

Теперь нам можно не бояться.

Генерируем сообщения об ошибке сами

Иногда нам нужно самим сгенерировать сообщение об ошибке. Для этого используется trigger_error:

trigger_error(‘ошибочка вышла: …’);

И эта ошибка будет также поймана нашим перехватчиком, который мы написали выше. А зачем генерировать сообщение об ошибке самим? Ну иногда просто бывают случаи, когда сообщение об ошибке не выкидывается само. Пример тому – выполнение функции mysql_query, которое может закончиться неудачно, а сообщения мы не увидим. Чтобы увидеть это сообщение, нам сначала нужно вызвать mysql_error, а потом передать текст ошибки с помощью trigger_error в обработчик:

<?
  …
  if (!mysql_query($sql)) {
    trigger_error('MySQL Error: '.mysql_error());
  }
  …
?>

Ну вот, теперь мы умеем контролировать вывод ошибок.





Читайте также:



9 Ответов на “Скрываем вывод ошибок в php”

  1. stussy
    Июль 4th, 2008

    закинул пост к себе на социалку

  2. Liiion911
    Январь 19th, 2009

    искал себе как оффнуть ошибки (тут нашел *php_flag display_errors off*) а потом прочитал статью до конца и решил, что сделаю как написано… када сделаю – напишу !!! =))

    Респект автору !!!

  3. Pasha
    Май 27th, 2009

    Спасибо! Познавательная статья.

  4. Владимир
    Июнь 13th, 2009

    я еще добавил в конец exit(‘Возникли неполадки в работе сайта сообщите пожалуйста: ****@mail.ru’); Очень удобно прекращает работу скрипта именно с того места где произошла ошибка. У меня важность функций как раз сверху вниз убывает. Так, например, если не могу связаться с базой, то дальнейшее выполнение скрипта бессмыслено.
    Только у меня не получилась вот эта часть:
    flock($f, LOCK_EX);
    fwrite($f, $err);
    flock($f, LOCK_UN);
    ЕЕ надо вставлять вместо fwrite($f, $err);?

  5. novice
    Июнь 14th, 2009

    Да, Владимир

  6. Владимир
    Июнь 18th, 2009

    flock($f, LOCK_EX);
    fwrite($f, $err);
    flock($f, LOCK_UN);

    Хоть убейте не получается! В файл записываются одни и те же ошибки.

  7. juray
    Август 6th, 2009

    Для фатальных ошибок не работает.
    Ошибки по-прежнему выводятся в браузер, errors.log не пополняется.

    Для trigger_error – работает великолепно.
    А вот если попадается, скажем, синтаксическая ошибка – вываливается сообщение в стандартный выходной поток.

  8. Настя
    Февраль 15th, 2011

    Жаль, что не нашла эту статью раньше, когда было очень, очень нужно :) В любом случае, нашла здесь полезное для себя. Большое спасибо!

  9. Привет
    Апрель 28th, 2011

    сссс
    сссссс
    ссссссс
    чясчясчясячсчяс
    ячсячсячсяч
    ячсячсячс
    счя
    яч
    сяч
    сяч
    ся
    чсяч
    сяч
    ся
    чс
    ячс
    ячс
    ячс
    ячс
    яч
    сяч
    сяч
    ся
    чс
    ячс
    ячс
    ячс
    ячс
    яч
    сяч
    сяч
    ся
    чс
    ячс
    ячс
    ячс
    ячс
    ыфвыфвыф

    чясячсячс
    ячсчясяч
    ячс
    ячс
    ячс
    яч
    сяч
    сяч
    ся
    чс
    1
    1
    1
    1
    1
    1
    11
    1
    1
    1
    1

    11
    1
    1
    2
    2
    2

    323
    43
    4

    433
    2322

    ропропр
    пр
    оп
    ро
    рпо
    рпо
    рп
    оен
    г
    нег
    не
    гне
    г
    г
    не
    о

    роь
    оо

    а
    рке
    н
    кег
    ено
    рпо
    рп
    ро
    л
    л
    нг
    лшг

    шгл
    ро
    рп
    опр
    оп
    ро
    ен
    ен
    г
    нег
    енг
    енг
    енг
    не
    ген
    ге
    но
    про
    прорпо
    про
    рп
    о
    о
    ен
    енг
    еген
    гне
    г
    нег
    нег
    оп
    про
    рп
    мит
    мит

    рпо
    рпо
    не
    гне
    г
    енг
    негорп

    о
    рпо
    рп
    о
    рпо
    рппр
    о
    по
    енгне
    ш
    гнл

    рпо
    рпо
    ео
    а
    рпо
    рп

    ео
    ен
    г
    ен
    не
    г
    р
    а
    пр
    п

    негннннннннннннннннннннннннннннннYour text to link…

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


© 2008 - 2012 i-novice.net | Все права защищены.