Як написати свій фреймворк на php. Обробка помилок. урок 4

  1. Обробка помилок handleError
  2. Обробка винятків handleException
  3. Висновок винятків на екран
  4. Висновок помилок на екран
  5. Як розробити фреймворк

Обробка помилок в 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

Тексти програм уроку подивитися і завантажити

Тексти програм кінцевого фреймворка подивитися і завантажити

Як розробити фреймворк

Розповісти друзям