PHP изключения GitHub
Този урок е преместен в моя github: https://github.com/codedokode/pasta/blob/master/php/exceptions.md - старата версия е представена по-долу, затова ви съветвам да отидете и да прочетете новата.
Как да използвам изключения в PHP
Ако изучавате ООП, вероятно сте се сблъскали с изключения. Ръководството за PHP описва командите try/catch/throw и накрая (налични от PHP 5.5), но всъщност не обяснява как да ги използвате. За да се справите с това, трябва да разберете защо изобщо са измислени.
И те са измислени, за да направят удобно обработване на грешки.
Да приемем например, че пишем приложение, за да покажем списък с потребители от файл на екран. Да приемем, че кодът изглежда по следния начин:
Тук всичко ли е наред? Не, не всички. Забравихме да направим обработка на грешки. Файлът може да не съществува, да не е достъпен, данните в него да са в грешен формат. Една добра програма, разбира се, трябва да се справя с такива ситуации и да показва подходящо съобщение.
Най-лесният (но лош) вариант е да поставите обработката на грешки и изходния код директно в loadUsersFromFile ():
Тази опция е лоша, тъй като сега повикващият на функцията loadUsersFromFile няма контрол върху обработката на грешки. Може би иска да покаже друго съобщение за грешка или иска да опита да потърси файла на друго място. Но нашата функция просто прекратява програмата, без да иска мнението му. Това е лошо.
Е, нека да подобрим кода и да пренапишем функцията, така че тя да върне масив от 2 елемента: ако всичко е наред, тогава елементът за успех съдържа true, а резултатният елемент съдържа масив от потребители. Ако възникне грешка, тогава успехът ще съдържа false и елементът за грешка ще съдържа текста на грешката.
Разбира се, ние също трябва да променим кода, който извиква функцията:
Кодът е много по-добър сега. Повикващият функцията може да обработва грешки, както иска. Но трябваше да платим за това, като усложнихме кода: сега, след всяко обаждане, трябва да напишем if и да проверим дали функцията е успяла. Когато има много функции и всяка може да върне грешка, кодът започва да се състои от половината от тези проверки.
Изключенията бяха измислени за решаване на проблема. Ако възникне грешка във функцията и тя не може да си свърши работата, тя извежда изключение с командата throw:
Изключение е обект от вградения PHP клас Exception (ръководство за изключение) или негов наследник. Обектът за изключение съдържа подробности за причините за грешката. Също така, PHP има и други класове изключения, които можете да използвате: http://php.net/manual/en/spl.exceptions.php
В PHP7 дефиницията е разширена: изключенията не трябва да наследяват от Exception, това може да бъде всеки клас, който реализира интерфейса Throwable и тъй като самото изключение го прилага, неговите наследници ще продължат да работят.
Също така можете да напишете свой собствен клас на изключение, наследявайки от Exception. В този случай можете дори да добавите свои собствени методи и свойства там. Трябва да напишете собствен клас, ако искате по-късно да уловите изключение, хвърлено от функцията, или да добавите някои допълнителни подробности за грешката (например името на файла, от който потребителите не могат да бъдат заредени).
Извършва се изключение в случай на необичайна ситуация, когато функцията открие, че не е в състояние да изпълни задачата си.
Изключението по подразбиране (ако не е уловено) излиза от всички извиквания на функциите в началото и излиза от програмата със съобщение за грешка. По този начин, ако не уловите изключения, все пак ще видите причината за грешката (и ако имате инсталирано разширението xdebug, тогава и стека на стека - веригата от извиквания на функции, в рамките на които се е случило). И вече не е нужно да пишете, ако:
Хвърлянето на изключение е донякъде подобно на връщането на стойност чрез return, но за разлика от return, хвърлянето на изключение не само излиза от функцията, където е било хвърлено, но и от всички функции на по-високо ниво, които са я извикали, ако не уловят това изключение. Тъй като изключение сигнализира за необичайна ситуация, която не може да бъде коригирана, изключенията обикновено не се улавят и им позволяват да прекратят изпълнението на програмата.
Ето един прост пример:
Изключения могат да бъдат уловени. Това е полезно в няколко случая. Понякога можем по някакъв начин да реагираме на неуспех: например, ако има грешка при изтеглянето на файл през мрежата, можем да направим пауза и да опитаме отново. За целта трябва да хванем изключението, хвърлено от функцията.
Също така, изключенията обикновено се улавят на най-горното ниво на програмата в уеб приложенията, за да направят своя собствена страница, информираща за грешката (тъй като PHP, с неизвестно изключение, прекратява програмата и потребителят вижда празна бяла страница в браузър, което е лошо). Приложенията, които се изпълняват в командния ред, а не в браузъра, обикновено нямат нужда, тъй като не са насочени към "обикновени" потребители.