Как включить или выключить отображение ошибок в PHP? Предыдущие сообщения об ошибках
В предыдущем уроке мы рассмотрели основы обработки исключений и различия между исключениями и ошибками. В этом уроке бы изучим опрядок обработки ошибок.
Ошибки в PHP можно разделить пользовательские и системные. К сожалению, перехватить системные ошибки стандартными средствами невозможно и единственный способ борьбы с ними - грамотное написание и отладка кода. Единственное, что можно (и нужно) сделать - запретить вывод в браузер любых сообщений об ошибках. Делается это при помощи функции error_reporting(). динственный параметр этой функции определяет какие ошибки разрешено выводить в браузер.
Параметр функции может быть комбинацией следующих констант
E_ERROR | Критические ошибки, прерывающие выполнение скрипта (например, ошибка выделения памяти) |
E_WARNING | Предупреждения |
E_PARSE | Синтаксические ошибки исходного кода |
E_NOTICE | Замечания |
E_CORE_ERROR | Критические ошибки, возникающие на этапе запуска исполнения скрипта |
E_CORE_WARNING | Предупреждения, возникающие на этапе запуска |
E_COMPILE_ERROR | Ошибки компиляции |
E_COMPILE_WARNING | Предупреждения компиляции |
E_USER_ERROR | Пользовательские ошибки, созданные с помощью функции trigger_error() |
E_USER_WARNING | Пользовательские предупреждения, созданные с помощью функции trigger_error() |
E_USER_NOTICE | Пользовательские замечания, созданные с помощью функции trigger_error() |
E_ALL | Все возможные ошибки, предупреждения и замечания |
E_STRICT | Замечания времени выполнения |
E_RECOVERABLE_ERROR | Критические ошибки, допускающие дальнейшее исполнение кода. |
Например:
Иногда возникают случаи, когда надо запретить вывод ошибок не для всего скрипта, а лишь для его части. В этом случае необходимо пользоваться оператором подавления ошибок "@" (собака). Будучи поставлен перед выражением, этот оператор запрещает вывод на зкран всех сообщений, предупреждений или замечаний, генерируемых выражением. Например:
Пользовательские ошибки могут быть без проблем перехвачены и обработаны, причем обработка ошибок построена таким образом, что может выполняться без завершения основного скрипта.
Для генерации ошибки служит функция trigger_error() , которой передаётся два параметра - тип ошибки и собственно её текст. Тип ошибки определяется стандартными константами, рассмотренными выше.
Например:
Вызов функции trigger_error не приводит к аварийному завершению скрипта, а значит весь последующий код будет нормально исполняться. Если же прервать выполнение всё-таки необходимо, то программист должен сделать это "вручную", используя средства языка.
Как и для исключений, для ошибок можно установить собственный обработчик. Делается это при помощи функции set_error_handler() , которой передаётся имя функции-обработчика и список типов ошибок, для которых эта функция вызывается. Функция имеет четыре параметра: номер ошибки, текст ошибки, имя файла и номер строки, где ошибка произошла. Например:
Если функция обработки ошибки возвращает true, то внутренний обработчик PHP не вызывается, а если false - то после выхода из пользовательской процедуры ошибка будут передана в стандартный внутренний обработчик. Это позволяет программисту реагировать только на часть возникающих ошибок, отдавая остальное старндартным обработчикам PHP.
Восстановить предыдущий обработчик можно, вызвав функцию restore_error_handler():
Таким способом можно включать и выключать обработчики ошибок по мере необходимости. Но злоупотреблять такими операциями не стоит - слишком высока вероятность запутаться и перепутать обработчики. В большинстве случаев достаточно одного, но хорошо написанного обработчика, который пишет ошибки в лог-файл или базу данных, пересылает их на email администратора и делает другие полезные операции.
Обработка ошибок - один из важнейших элементов написания скриптов. Некачественно написанный срипт может стать не только головной болью веб-мастера или администратора сайта. "Бажный" (от слова "баг" - ошибка) скрипт представляет серьёзную угрозу безопасности. В руках умелого взломщика текст ошибки превращается в отмычку, открывающую доступ ко всему содержимому сайта, а может быть и сервера.
Неотъемлемой частью программирования является выявление ошибок в коде. Будь программист хоть семь пядей во лбу, все равно, он будет совершать ошибки, иногда даже банальные. Этому способствует сама природа человека. Поэтому за отладкой и выявлением ошибок в коде программист проводит достаточно большую часть времени. Соответственно, чем гибче и удобнее существуют инструменты для выявления ошибок в коде, и чем лучше программист ими владеет, - тем выше его продуктивность.
Поскольку PHP является скриптовым языком программирования, то все ошибки, допущенные в коде, выявляются по ходу исполнения кода. Программисту PHP предстоит сталкиваться как со стандартными ошибками, присущими программированию в целом, так и с довольно скрытыми ошибками – такими как опечатки в именовании переменных.
Язык PHP предусматривает два механизма выявления ошибок в скрипте в процессе его выполнения: стандартный механизм ошибок PHP и механизм исключений. В PHP множество функционала использует стандартный механизм ошибок, поэтому не знать о нем нельзя. Поэтому в данной статье речь пойдет именно об этом механизме.
Стандартный механизм ошибок PHP довольно прост – если в процессе выполнения сценария интерпретатор PHP сталкивается с какой-либо ошибкой – он пытается известить об этом программиста. Однако настроек этого механизма предусмотрено довольно много, поэтому разобраться в них программисту, познающему PHP, довольно сложно.
Видим ошибки
Так, для того, чтобы PHP отображал ошибки прямо на странице, необходимо установить специальный параметр в коде:
ini_set("display_errors", 1); //display_errors отвечает за отображение ошибок прямиком на странице. Если 0 – ошибки не отображаются
Теперь, при возникновении какой-либо ошибки в скрипте, интерпретатор выведет информацию о ней на странице. Например, если запустить скрипт с несуществующей функцией:
ini_set("display_errors", 1);
echo "
Строка, которая будет отображена
";echo abrakadabra();
echo "
Строка, которая не будет отображена из-за ошибки
";то на странице отобразится такая ошибка:
Фатальная ошибка. Такого рода ошибка означает, что скрипт прерывает свою работу, и далее идущий код не будет выполнен.
Отображение ошибок скрипта на странице используется только для отладки самого скрипта, поэтому при запуске кода в боевой среде параметру display_errors
устанавливают значение 0.
Вообще, в PHP имеется ошибки разных категорий значимости: некоторые из них прерывают дальнейшее выполнение кода – другие нет, одни можно перехватывать – другие нельзя. Полный перечень категорий ошибок приведен ниже:
Значение | Константа | Описание | Возможность |
1 | E_ERROR | Неустранимая ошибка | Нет |
2 | E_WARNING | Исправимая ошибка | Да |
4 | E_PARSE | Ошибка парсера | Нет |
8 | E_NOTICE | Потенциальная ошибка | Да |
16 | E_CORE_ERROR | Аналогично E_ERROR, но генерируется ядром PHP | Нет |
32 | E_CORE_WARNING | Аналогично E_WARNING, но генерируется ядром PHP | Нет |
64 | E_COMPILE_ERROR | Аналогично E_ERROR, но генерируется Zend Engine | Нет |
128 | E_COMPILE_WARNING | Аналогично E_WARNING, но генерируется Zend Engine | Нет |
256 | E_USER_ERROR | Аналогично E_ERROR, но инициируется вызовом trigger_error() | Да |
512 | E_USER_WARNING | Аналогично E_WARNING, но инициируется вызовом trigger_error() | Да |
1024 | E_USER_NOTICE | Аналогично E_NOTICE, но инициируется вызовом trigger_error() | Да |
2048 | E_STRICT | Сообщение от исполнительной среды с рекомендациями по улучшению качества кода (начиная с PHP5) | - |
4096 | E_RECOVERABLE_ERROR | Опасная, но не фатальная ошибка(например, несоответствие типа) | Да |
8192 | E_DEPRECATED | Предупреждение об использовании устаревшей функции или возможности | Да |
16384 | E_USER_DEPRECATED | Предупреждение об использовании устаревшей функции или возможности, инициированное в коде | Да |
32767 | E_ALL | Все ошибки | Нет |
Для удобства предусмотрены константы, которые используются для определения уровня обработки ошибок, построения бит-маски. Константы имеют "говорящие" имена. Глядя на константу - мы можем сказать, что ошибка уровня E_PARSE возникает в случае синтаксической ошибки, E_NOTICE - это напоминание программисту о нарушении "хорошего стиля" программирования на PHP.
По умолчанию включено значение режима генерации сообщений об ошибках E_ALL & ~E_NOTICE , что соответствует выводу всех сообщений, не относящихся к категории E_NOTICE . Программист может гибко настроить, какие категории ошибок ему необходимо видеть на странице. Для того, чтобы изменить режим генерации ошибок, необходимо изменить конфигурационный параметр error_reporting . Чтобы включить отображение любых ошибок, необходимо задать данному параметру значение E_ALL :
Например, если запустить следующий код:
ini_set("display_errors", 1);
ini_set("error_reporting", E_ALL);
Мы получим ошибки сразу двух категорий (notice и warning):
Когда используется необъявленная переменная – появляется ошибка E_NOTICE
. Когда соединение с базой данных MySQL (или другой) завершается неудачей - интерпретатор PHP сообщает об ошибке уровня E_WARNING
.
Логируем ошибки
Если даже конфигурационный параметр display_errors
установлен в 0, все равно должна быть возможность просматривать наличие случившихся ошибок в процессе выполнения скрипта. Таким образом, в случае если случится ошибка – мы должны знать, где и почему она случилась. Для этих целей в PHP существуют настройки логирования ошибок.
По умолчанию средствами языка PHP ошибки нигде не логируются. Чтобы это изменить, необходимо изменить конфигурационный параметр log_errors
в 1 с 0:
ini_set("log_errors", 1);
В таком случае, ошибки автоматически будут записываться в файл, указанный в конфигурационном параметре error_log
. Параметр error_log
также можно изменить, указав путь к желаемому файлу, куда будут записываться ошибки:
ini_set("error_log", "/var/log/php_errors.log");
Так, для кода:
ini_set("display_errors", 1);
ini_set("error_reporting", E_ALL);
ini_set("log_errors", 1);
ini_set("error_log", __DIR__ . "/log.txt");
$db = mysql_connect($db_host, "user", "password");
В лог-файл записывается аналогичная информация, которая выводится на страницу:
PHP Notice: Undefined variable: db_host in Z:\home\test\www\index.php on line 7
PHP Warning: mysql_connect(): Access denied for user "user"@"localhost" (using password: YES) in Z:\home\test\www\index.php on line 7
Обрабатываем ошибки
Ошибки делятся на перехватываемые и не перехватываемые. Некритические ошибки можно перехватывать пользовательским кодом. Сводная таблица описания категорий ошибок раскрывает информацию, какие категории ошибок можно перехватывать.
Для того, чтобы перехватывать некритические ошибки в коде, достаточно реализовать и объявить собственную функцию и передать ее название в функцию set_error_handler
. При этом, в реализованную функцию передаются 5 параметров:
- уровень ошибки в виде целого числа;
- сообщение об ошибки в виде строки;
- имя файла, в котором произошла ошибка, в виде строки;
- номер строки, в которой произошла ошибка, в виде целого числа;
- массив всех переменных, существующих в области видимости, где произошла ошибка. Причем, будут включены также и глобальные переменные.
Вывод
PHP имеет мощные средства обработки и управления стандартным распространением ошибок. Поэтому отловить ту или иную ошибку не составит труда при условии, что скрипт грамотно сконфигурирован. Знания этой области является неотъемлемыми любого PHP-программиста, поскольку множество кода использует описанный выше механизм
Часто слышал о такой проблеме от других пользователей. Одним из-за хостера нужно скрыть появляющиеся ошибки, другим наоборот - понять, что происходит с их кодом, потому что ни одна ошибка не показывается. В этой статье постараюсь показать все основные способы отобразить / скрыть ошибки.
В примере специально допущена ошибка, но она НЕ будет отображена
$value = @$var[$key];
2)
Также можно перед проверяемым скриптом PHP можно вставить настройку параметра отображения ошибок (display_errors
). Он может приобретать значение либо On (показывать), либо Off (скрыть).
Ini_set("display_errors","On");
error_reporting("E_ALL");
И соответственно после кода, который проверялся на ошибки, выставить параметр обратно.
Ini_set("display_errors","Off");
Например, Вы хотите увидеть ошибки в скрипте
Ini_set("display_errors", "On"); // сообщения с ошибками будут показываться
error_reporting(E_ALL); // E_ALL - отображаем ВСЕ ошибки
$value = $var[$key]; // пример ошибки
ini_set("display_errors", "Off"); // теперь сообщений НЕ будет
Можно выставить наоборот (в верхнем off, а в нижнем on), чтобы в конкретном отрезке кода ошибки НЕ отображались.
Php_flag display_errors On
#показать все ошибки кроме предупреждений (Notice)
php_value error_reporting "E_ALL & ~E_NOTICE"
В php.ini :
Error_reporting = E_ALL
display_errors On
В верхней строке выбираем все виды ошибок, в нижней даём добро на их отображение.
После правок необходимо перезапустить Apache, чтобы настройки были изменены и вступили в силу (graceful или restart):
Sudo apachectl -k graceful
В каком порядке обрабатывается параметр ошибок В самом начале учитывается параметр php.ini , затем.htaccess , а после то, что указано непосредственно в скрипте PHP. Так что если что-то не сработало, то смотрим по цепочку выше, возможно, там настройка другая.Как обычно спасибо за внимание и удачи! Надеюсь статья была полезна!
- print , echo и другие функции, производящие вывод
- Необработанные разделы, предшествующие
Если источник ошибки упоминается как за закрытие?> то здесь выписывается какой-то пропущенный или необработанный текст. Маркер конца PHP не завершает выполнение script при этом точка. Любые символы текста/пробела после того, как они будут выписаны как содержимое страницы до сих пор.
Общепринято, в частности, новичкам, что trailing ?> PHP теги close должны быть опущены. Это предотвращает небольшую часть этих случаев. (Чаще всего сценарии include()d являются виновниками.)
- Источник ошибки, указанный как "Неизвестно в строке 0"
Обычно это расширение PHP или php.ini, если источник ошибок конкретизируется.
- Иногда параметр настройки потока gzip или ob_gzhandler .
- Но это может быть и любой загруженный в два раза модуль extension= генерирование неявного сообщения о запуске/предупреждении PHP.
- Предыдущие сообщения об ошибках
Если другой оператор или выражение PHP вызывает предупреждение или уведомление распечатывается, что также считается преждевременным выходом.
В этом случае вам нужно избежать ошибки, задержать выполнение оператора или подавить сообщение, например. isset() или @() - когда либо не препятствует отладке позже.
- Значения байтов байтов в начале php файла. Изучите ваши php файлы с помощью шестнадцатеричного редактора, чтобы узнать, является ли этот случай. Они должны начинаться с байтов 3F 3C . Вы можете безопасно удалить спецификацию EF BB BF с начала файлов.
- Явный вывод, например вызовы echo , printf , readfile , passthru , код до
DO CHECK FOR BLANK SPACES HERE AS WELL; THIS LINE (blank line) SHOULD NOT EXIST.
Большая часть времени это должно решить ваш problem.Do проверить все файлы, связанные с файлом вам require .
Примечание. Иногда EDITOR (IDE), например gedit (стандартный Linux-редактор), добавляет одну пустую строку в файл save save. Этого не должно быть. Если вы используете linux. вы можете использовать редактор VI для удаления пробела/строк после?> в конце страницы.
Если это не ваше дело, тогда вы можете использовать ob_start для буферизации вывода, как показано ниже:
Это приведет к буферизации вывода, и ваши заголовки будут созданы после буферизации страницы.
Вместо строки ниже
//header("Location:".ADMIN_URL."/index.php");
написать
Echo("location.href = "".ADMIN_URL."/index.php?msg=$msg";");
?>
Преднамеренное:
Если у вас error_reporting или display_errors отключено на php.ini , то предупреждение не появится. Но игнорирование ошибок не вызовет проблемы далеко. Заголовки по-прежнему не могут быть отправлены после преждевременного выхода.
Поэтому, когда header("Location: ...") перенаправляет молча, рекомендуется проконтролировать предупреждения. Обозначить их двумя простыми командами на вызов script:
Error_reporting(E_ALL); ini_set("display_errors", 1);
Или set_error_handler("var_dump"); , если все остальное не работает.
Говоря о переадресации заголовков, вы должны часто использовать идиому вроде это для конечных путей кода:
Exit(header("Location: /finished.html"));
Предпочтительно даже функция полезности, которая печатает сообщение пользователя в случае сбоев header() .
Буферизация вывода в качестве обходного путиОн может скрывать пробелы для вывода HTML. Но как только приложение логические попытки отправить двоичный контент (например, сгенерированное изображение), буферизованный посторонний выход становится проблемой. (Необходимость ob_clean() как предыдущий вариант.)
Буфер ограничен по размеру и может быть легко переполнен, если оставить его по умолчанию. И это не редкость, трудно отследить когда это произойдет.
Оба подхода могут стать ненадежными - в частности, при переключении между разработки и/или производственные серверы. Именно поэтому буферизация вывода широко считается просто костылем/строго обходным путем.
Это сообщение об ошибке запускается, когда что-либо отправляется перед отправкой заголовков HTTP (с setcookie или header). Общие причины вывода чего-либо перед заголовками HTTP:
Случайные пробелы, часто в начале или в конце файлов, например:
Чтобы избежать этого, просто оставьте закрытие?>