Как включить или выключить отображение ошибок в PHP? Предыдущие сообщения об ошибках

02.04.2020 Новости 


В предыдущем уроке мы рассмотрели основы обработки исключений и различия между исключениями и ошибками. В этом уроке бы изучим опрядок обработки ошибок.


Ошибки в 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-программиста, поскольку множество кода использует описанный выше механизм


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

В скрипте PHP1) В 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), чтобы в конкретном отрезке кода ошибки НЕ отображались.

В файле.htaccess Чаще всего проблему решают именно указанием настроек в файле .htaccess , который располагается в корневой директории сайта. В строке php_flag display_errors нужно также выставить On или Off

Php_flag display_errors On
#показать все ошибки кроме предупреждений (Notice)
php_value error_reporting "E_ALL & ~E_NOTICE"

В файле php.ini Как видите, параметр можно указать в нескольких местах. Однако, если у Вы хотите, чтобы целиком на сайте этот параметр имел определённое значение, то проще выставить его в файле php.ini.(к нему на хостинге не всегда может быть доступ), но в этом случае можно будет даже обойти настройки всего хостинга

В 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() или @() - когда либо не препятствует отладке позже.

    Нет сообщения об ошибке

    Если у вас 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:

      Случайные пробелы, часто в начале или в конце файлов, например:

    Чтобы избежать этого, просто оставьте закрытие?>

    • Значения байтов байтов в начале 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 для буферизации вывода, как показано ниже:

      Возможное решение 2:

      Это приведет к буферизации вывода, и ваши заголовки будут созданы после буферизации страницы.

      Вместо строки ниже

      //header("Location:".ADMIN_URL."/index.php");

      написать

      Echo("location.href = "".ADMIN_URL."/index.php?msg=$msg";");

      ?>