Як увімкнути або вимкнути відображення помилок у 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 в 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 , потім. Тож якщо щось не спрацювало, то дивимося по ланцюжку вище, можливо, там налаштування інше.

Як завжди дякую за увагу та удачі! Сподіваюся, стаття була корисна!

    Навмисне:

    • 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";");

      ?>