Як написати свій фреймворк на php. Обробка помилок. урок 4
- Обробка помилок handleError
- Обробка винятків handleException
- Висновок винятків на екран
- Висновок помилок на екран
- Як розробити фреймворк
Обробка помилок в php , Це дуже цікава річ. З одного боку, в цій мові є все, щоб обробити і вивести помилку. З іншого, в ньому є такий тип помилок, який жодним чином не обробляється. це Fatal Error , або помилки синтаксису.
Помилки таких типів не потрапляють в обробники, вони просто виводяться як є.
ДисклеймерКод нижче, без тіні сумніву, взятий з фреймворка Yii. Мета даного циклу ні в тому щоб написати свій велосипед, а в тому щоб знати, як цей велосипед в принципі влаштований.
Отже, в минулих уроках ми створили макет додатки, пару сторінок, роутер і шаблонизатор . Ми навіть оголосили такий клас
class Except extends Exception {}який нічого не робить. Зайду трохи вперед, він і зараз нічого не буде робити. Але ми зрозуміємо навіщо він в принципі буде потрібен в подальшому.
Коли в коді ми обробляли якусь бізнес логіку, ми викидали виняток, таким кодом
throw new Except ( 'Error message');це призводило до того, що на екрані виводилася подібна запис
Fatal error: Uncaught exception 'Except' with message 'File Z: \ home \ analize \ ideal / application / views / page / pages / B2.php not found' in Z: \ home \ analize \ ideal \ ideal \ classes \ Controller .php: 29 Stack trace: # 0 Z: \ home \ analize \ ideal \ ideal \ classes \ Controller.php (43): Controller -> _ renderPartial ( 'Z: \ home \ analize ...', Array, true) # 1 Z: \ home \ analize \ ideal \ application \ views \ page \ read.php (2): Controller-> renderPartial ( 'pages / B2') # 2 Z: \ home \ analize \ ideal \ ideal \ classes \ Controller.php (26): include ( 'Z: \ home \ analize ...') # 3 Z: \ home \ analize \ ideal \ ideal \ classes \ Controller.php (43): Controller -> _ renderPartial ( 'Z : \ home \ analize ... ', Array, true) # 4 Z: \ home \ analize \ ideal \ ideal \ classes \ Controller.php (53): Controller-> renderPartial (' read ', Array, true) # 5 Z: \ home \ analize \ ideal \ application \ controllers \ PageController.php (4): Controller-> render ( 'read', Array) # 6 [internal function]: PageController-> actionRead ( 'B2') # 7 Z: \ home \ analize \ ideal \ ideal \ classes \ Controller.php (7): call_user_func_array (Array, Array) # 8 Z: \ hom e \ analize \ ideal \ ideal \ classes \ App.php in Z: \ home \ analize \ ideal \ ideal \ classes \ Controller.php on line 29Це вбудований обробник помилок php, вивів для нас цю вичерпну інформацію. Тут є все що нам потрібно для того, щоб з'ясувати, що ж сталося: саме повідомлення, стек виклику функцій з файлами і методами. Ми бачимо навіть параметри, які подані в тих або методах стека. Все що потрібно їсти, але виводиться це не дуже красиво.
Для того, щоб зробити це більш легкотравним, нам буде потрібно встановити обробник виключень, через метод set_exception_handler. Ми обробляємо не тільки виключення, але і помилки php (все, крім fatal), тому встановимо ще обробник set_error_handler.
Але перед цим, додамо в клас App з ideal / classes / App.php кілька методів
public function handleError ($ code, $ message, $ file, $ line) {}; public function handleException ($ exception) {}; public function displayError ($ code, $ message, $ file, $ line) {}; public function displayException ($ exception) {}; protected function initSystemHandlers () {};В першу чергу напишемо initSystemHandlers
protected function initSystemHandlers () {set_exception_handler (array ($ this, 'handleException')); set_error_handler (array ($ this, 'handleError'), error_reporting ()); }Все що він робить, це встановлює два глобальних обробника винятків, перший для винятків, другий для помилок
Наведемо два цих обробника.
Обробка помилок handleError
public function handleError ($ code, $ message, $ file, $ line) {if ($ code ∓ error_reporting ()) {restore_error_handler (); restore_exception_handler (); try {$ this-> displayError ($ code, $ message, $ file, $ line); } Catch (Exception $ e) {$ this-> displayException ($ e); }}}error_reporting - це встановлений десь вище, рівень виведення помилок. Точніше які помилки виводити. Має купу варіацій, але якщо грубо, то E_ALL - виводити всі помилки, 0 - не виводити ніякі помилки. Значення порівнюється побітовим and зі значенням $ code. Якщо викинути коду помилки дозволено виводиться на екран, то продовжуємо.
restore_exception_handler і restore_error_handler - знімають всі встановлені обробники. В кінці повинен залишитися тільки один і цей один - це поточний метод.
Далі пробуємо вивести помилку на екран, якщо відбувається щось виняткове, то намагаємося вивести це виняток.
Обробка винятків handleException
public function handleException ($ exception) {restore_error_handler (); restore_exception_handler (); $ This-> displayException ($ exception); }Ідентично першим методом.
далі два методи для виведення помилок і виключень
Висновок винятків на екран
public function displayException ($ exception) {echo '<h1>'. get_class ($ exception). "</ h1> \ n"; echo '<p>'. $ exception-> getMessage (). ' ( '. $ Exception-> getFile ().': '. $ Exception-> getLine ().') </ P> '; echo '<pre>'. $ exception-> getTraceAsString (). '</ pre>'; }Тут без сюрпризів, у стандартного класу винятку Exception, є вбудований метод виведення стека викликів функцій. Також є метод виведення файлу і лінії.
get_class - то, навіщо був зроблений окремий клас Except. Ви можете створити скільки завгодно таких класів, і назвати їх все по різному (SQLExcept, CacheExcept і т.д.). Тоді подивившись на помилку, ви відразу ж визначте, яка частина логіки вашої програми зламалася. Крім того, ви можете перевизначити метод getMessage і вивести в ньому наприклад SQL запит, який викликав збій.
У наступному уроці, ми поговоримо про моделі і роботі з БД, ось тут нам і знадобляться ці винятки
Висновок помилок на екран
З помилками все трохи складніше. У нас немає класу помилок, ви можете його створити, але поки ви просто виводимо стек виклику за допомогою функції debug_backtrace
public function displayError ($ code, $ message, $ file, $ line) {echo "<h1> PHP Error [$ code] </ h1> \ n"; echo "<p> $ message ($ file: $ line) </ p> \ n"; echo '<pre>'; $ Trace = debug_backtrace (); if (count ($ trace)> 3) {$ trace = array_slice ($ trace, 3); } Foreach ($ trace as $ i => $ t) {if (! Isset ($ t [ 'file'])) $ t [ 'file'] = 'unknown'; if (! isset ($ t [ 'line'])) $ t [ 'line'] = 0; if (! isset ($ t [ 'function'])) $ t [ 'function'] = 'unknown'; echo "# $ i {$ t [ 'file']} ({$ t [ 'line']}):"; if (isset ($ t [ 'object']) && is_object ($ t [ 'object'])) echo get_class ($ t [ 'object']) .'-> '; echo "{$ t [ 'function']} () \ n"; } Echo '</ pre>'; exit (); }Стек виклику може бути величезним, і тому обмежуємо його глибину 3-ма методами.
Тепер додамо в код нашого класу App, ще один метод
public function __construct () {$ this-> initSystemHandlers (); }Тобто встановлюємо наші обробники, в момент створення екземпляра класу App
Ось і все, тепер виключення виводяться так, як ми цього хочемо
Подивитися, як працює виняток, можна на тестовому сайті. Якщо ви пам'ятаєте, то якщо у нас не було файлу в папці виду, ми викидали повідомлення
throw new Except ( 'File'. $ fullpath. 'not found');Тому просто перейдемо на неіснуючий файл, в контролері page http://ideal.xdan.ru/about1111.html
Тексти програм уроку подивитися і завантажити
Тексти програм кінцевого фреймворка подивитися і завантажити
Як розробити фреймворк
Розповісти друзям