Як увімкнути або вимкнути відображення помилок у 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 в 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 , потім. Тож якщо щось не спрацювало, то дивимося по ланцюжку вище, можливо, там налаштування інше.Як завжди дякую за увагу та удачі! Сподіваюся, стаття була корисна!
- 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:
Випадкові прогалини, часто на початку або в кінці файлів, наприклад:
Щоб уникнути цього, просто залиште закриття?