Включение вывода ошибок уровня Notice, Deprecated или Strict, может спровоцировать дополнительные сообщения уровня Warning, а то и приводить к фатальным ошибкам от некоторых PHP библиотек или компонентов. К таким компонентам относится, например, популярный SapiEmitter из ZendFramework, который проверяет отправку заголовков с помощью директивы headers_sent(). Это нужно иметь в виду, если в ходе отладки вы пытаетесь найти проблемное место, а дойти до него не можете из-за банального падения SapiEmittera в Fatal при слишком подробном выводе ошибок.
Итак, приступим к подробному рассмотрению проблемы.
Допустим, мы включили отображение всех ошибок:
E_ALL
И увидели на экране несколько Notice и Warning.
Включим подавление Notice, чтобы отфильтровать Warning
E_ALL & ~E_NOTICE
К своему удивлению мы зачастую можем обнаружить, что Warning-и исчезли вместе с Notice!
Если же включить фильтрацию Warning, но оставить отображение Notice, то, действительно, останутся только Notice:
E_ALL & ~E_WARNING
Куда деваются Warning-и при отключении Notice? Оказывается, если внимательно почитать содержимое Warning-ов, то можно обнаружить хрестоматийные ошибки типа headers already sent, указывающие на преждевременно отправленные заголовки. Так бывает, если на экран что-то выводится раньше, чем оно должно быть на самом деле. А бывает это очень часто вовсе не из-за небрежно написанного кода, а в результате вывода ошибок на экран — именно эти Notice (а также Deprecated и т.п.) портят заголовки своим преждевременным появлением.
Таким образом, отображение ошибок одного уровня может породить ошибки другого уровня.
Мораль: подавление предупреждений типа Notice скрывает множество предупреждений типа Warning и других.
Поэтому, для отлова всех возможных узких мест необходимо
- Включить отображение всех ошибок E_ALL с подавлением Notices. Мы получим список ошибок типа Warning, которые не будут зависеть от Notices.
- После избавления от Warning-ов на предыдущем шаге включаем отображение Notices и получаем ещё один набор Warning-ов, вызванных отображением Notices. Устраняем эти Warning-и за исключением, пожалуй, сообщений типа «headers already sent».
- Затем устраняем Notices, как наименее критичные предупреждения.
И ещё одна практическая рекомендация.
При работе с популярным сервером OpenServer я столкнулся со странными «предпочтениями» браузера Google Chrome при включении/отключении показа ошибок в коде PHP. А имено, браузер показывал ошибки через раз или вовсе отказывался это делать, если я пользовался стандартной директивой PHP error_reporting(…), тогда как аналогичная по функционалу директива ini_set(«error_reporting», …) в том же самом месте работала безотказно. Кроме того, браузеру было абсолютно наплевать на параметр display_error, значение которого ни на что не влияло.
Я связываю всё это с какими-то внутренними несоответствиями внутри OpenServer, поскольку на самом деле такого быть не должно.
В свете вышесказанного для отладки я сейчас использую исключительно директиву ini_set.