Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ

Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠ°Π½ΠΈΠ΅

Π—Π°ΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅: Π‘ΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅ класс Exception

МодСль ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ PHP Π½Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅Ρ‚ модСль ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ Π΄Ρ€ΡƒΠ³ΠΈΡ… языков программирования. PHP ΡƒΠΌΠ΅Π΅Ρ‚ Π²Ρ‹Π±Ρ€Π°ΡΡ‹Π²Π°Ρ‚ΡŒ β€” throw β€” ΠΈ Π»ΠΎΠ²ΠΈΡ‚ΡŒ β€” catch β€” ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ. Код Π·Π°ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ Π² Π±Π»ΠΎΠΊ try, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ вСроятных ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ. ΠšΠ°ΠΆΠ΄ΠΎΠΌΡƒ Π±Π»ΠΎΠΊΡƒ try ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‚ ΠΊΠ°ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ ΠΎΠ΄ΠΈΠ½ Π±Π»ΠΎΠΊ catch ΠΈΠ»ΠΈ finally.

Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Β«Π²ΡΠΏΠ»Ρ‹Π²Π°Ρ‚ΡŒΒ» ΠΏΠΎ стСку Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΏΠΎΠΊΠ° Π½Π΅ Π½Π°ΠΉΠ΄Ρ‘Ρ‚ Π±Π»ΠΎΠΊ catch, Ссли функция выбросила ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Π° Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ области видимости Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, которая Π΅Ρ‘ Π²Ρ‹Π·Π²Π°Π»Π°, Π½Π΅Ρ‚ Π±Π»ΠΎΠΊΠ° catch. PHP Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Π±Π»ΠΎΠΊ finally, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ встрСтит ΠΏΠΎ ΠΏΡƒΡ‚ΠΈ. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ Ρ„Π°Ρ‚Π°Π»ΡŒΠ½ΠΎΠΉ ошибкой, ΠΊΠΎΠ³Π΄Π° стСк Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² Π½Π΅ встрСчаСт Π±Π»ΠΎΠΊ catch ΠΈ разворачиваСтся Π΄ΠΎ глобальной области видимости, Ссли Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ Π½Π΅ установил Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ.

Π’ ΠΊΠΎΠ΄Π΅ допустимо Π²Ρ‹Π±Ρ€Π°ΡΡ‹Π²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ, Ρ‚ΠΈΠΏ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΡ€ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠΌ instanceof соотвСтствуСт интСрфСйсу Throwable. ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° Π²Ρ‹Π±Ρ€ΠΎΡΠΈΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π½Π΅ выполняСт это условиС, ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Ρ‚ ΠΊ Ρ„Π°Ρ‚Π°Π»ΡŒΠ½ΠΎΠΉ ошибкС PHP.

Π‘ PHP 8.0.0 ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово throw стало Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ΠΌ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Ρ€Π°Π·Ρ€Π΅ΡˆΠΈΠ»ΠΈ Π·Π°ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ Π² контСкстС выраТСния. Π’ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ… вСрсиях это слово Π±Ρ‹Π»ΠΎ инструкциСй ΠΈ Π΅Ρ‘ записывали Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ строкС.

catch

Π‘Π»ΠΎΠΊ catch опрСдСляСт, ΠΊΠ°ΠΊ Ρ€Π΅Π°Π³ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ выбросил ΠΊΠΎΠ΄. Π‘Π»ΠΎΠΊ catch опрСдСляСт ΠΎΠ΄ΠΈΠ½ ΠΈΠ»ΠΈ большС Ρ‚ΠΈΠΏΠΎΠ² ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ ΠΈΠ»ΠΈ ошибок, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠ½ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚, ΠΈ Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π±Π»ΠΎΠΊ присвоит ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅. Π”ΠΎ PHP 8.0.0 ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π»ΠΎΡΡŒ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ. ΠžΠ±ΡŠΠ΅ΠΊΡ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Π±Π»ΠΎΠΊ catch, с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ столкнутся ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΈΠ»ΠΈ ошибка Ρ‚ΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° ΠΈΠ»ΠΈ ΠΏΠΎΠ΄Ρ‚ΠΈΠΏΠ°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ Π±Π»ΠΎΠΊ.

Π‘Π»ΠΎΠΊΠΈ catch Π·Π°ΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‚ ΠΎΠ΄ΠΈΠ½ Π·Π° Π΄Ρ€ΡƒΠ³ΠΈΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Ρ€Π°Π·Π½Ρ‹Ρ… классов. ΠΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎΠ΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅, ΠΊΠΎΠ³Π΄Π° Π±Π»ΠΎΠΊ try Π½Π΅ выбросил ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, продолТится послС послСднСго Π±Π»ΠΎΠΊΠ° catch, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠ»ΠΈ Π² ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ. Π’Π½ΡƒΡ‚Ρ€ΠΈ Π±Π»ΠΎΠΊΠ° catch допустимо Π²Ρ‹Π±Ρ€Π°ΡΡ‹Π²Π°Ρ‚ΡŒ, Π° Ρ‚ΠΎΡ‡Π½Π΅Π΅ β€” ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ Π²Ρ‹Π±Ρ€Π°ΡΡ‹Π²Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Ρ‡Π΅Ρ€Π΅Π· ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ слово throw. PHP ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π° послС Π±Π»ΠΎΠΊΠ° catch, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ сработал, Ссли Π²Π½ΡƒΡ‚Ρ€ΠΈ Π±Π»ΠΎΠΊΠ° Π½Π΅ выбросили ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.

ΠŸΡ€ΠΈ появлСнии ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ PHP Π½Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ ΠΊΠΎΠ΄, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΈΠ΄Ρ‘Ρ‚ Π·Π° инструкциСй, Π° попытаСтся Π½Π°ΠΉΡ‚ΠΈ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ подходящий Π±Π»ΠΎΠΊ catch. PHP выдаст Ρ„Π°Ρ‚Π°Π»ΡŒΠ½ΡƒΡŽ ΠΎΡˆΠΈΠ±ΠΊΡƒ с сообщСниСм Uncaught Exception ..., Ссли ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π½Π΅ ΠΏΠΎΠΉΠΌΠ°Π»ΠΈ ΠΈ Ρ‡Π΅Ρ€Π΅Π· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ set_exception_handler() Π½Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠ»ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ.

Π‘ PHP 7.1.0 Π² Π±Π»ΠΎΠΊΠ΅ catch допустимо ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Ρ‡Π΅Ρ€Π΅Π· символ Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠΉ Ρ‡Π΅Ρ€Ρ‚Ρ‹ |. Π­Ρ‚ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ, ΠΊΠΎΠ³Π΄Π° Ρ€Π°Π·Π½Ρ‹Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΈΠ· Ρ€Π°Π·Π½Ρ‹Ρ… ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΠΉ классов ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ.

Π‘ PHP 8.0.0 имя ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ для ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΏΠΎΠΉΠΌΠ°Π» Π±Π»ΠΎΠΊ, Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ. PHP Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ Π±Π»ΠΎΠΊ catch, Π½ΠΎ Ρƒ Π±Π»ΠΎΠΊΠ° Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ доступа ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ выбросил ΠΊΠΎΠ΄, Ссли ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ Π½Π΅ ΡƒΠΊΠ°Π·Π°Π»ΠΈ.

finally

Π‘Π»ΠΎΠΊ finally Ρ‚Π°ΠΊΠΆΠ΅ допустимо ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ послС ΠΈΠ»ΠΈ вмСсто Π±Π»ΠΎΠΊΠΎΠ² catch. PHP Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ ΠΊΠΎΠ΄ Π² Π±Π»ΠΎΠΊΠ΅ finally послС Π±Π»ΠΎΠΊΠΎΠ² try ΠΈ catch, нСзависимо ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, выбросил Π»ΠΈ ΠΊΠΎΠ΄ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, ΠΈ Π΄ΠΎ возобновлСния Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ выполнСния.

ЗаслуТиваСт внимания взаимодСйствиС ΠΌΠ΅ΠΆΠ΄Ρƒ Π±Π»ΠΎΠΊΠΎΠΌ finally ΠΈ инструкциСй return. PHP Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ Π±Π»ΠΎΠΊ finally, Π΄Π°ΠΆΠ΅ Ссли встрСтит Π²Π½ΡƒΡ‚Ρ€ΠΈ Π±Π»ΠΎΠΊΠΎΠ² try ΠΈΠ»ΠΈ catch ΠΈΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ return. Π‘ΠΎΠ»ΡŒΡˆΠ΅ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠΎΠ³Π΄Π° PHP встрСчаСт ΠΈΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ return, ΠΎΠ½ вычисляСт Π΅Ρ‘, Π½ΠΎ Π²Π΅Ρ€Π½Ρ‘Ρ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ послС выполнСния Π±Π»ΠΎΠΊΠ° finally. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, PHP Π²Π΅Ρ€Π½Ρ‘Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΠ· Π±Π»ΠΎΠΊΠ° finally, Ссли Π±Π»ΠΎΠΊ finally Ρ‚ΠΎΠΆΠ΅ содСрТит ΠΈΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ return.

Π”Ρ€ΡƒΠ³ΠΎΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ‡Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ взаимодСйствиС встрСчаСтся ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡΠΌΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ сгСнСрировали ΠΈ Π±Π»ΠΎΠΊ try, ΠΈ Π±Π»ΠΎΠΊ finally. ΠŸΡ€ΠΈ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΎΠ±ΠΎΠΈΠΌΠΈ Π±Π»ΠΎΠΊΠ°ΠΌΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π±Π»ΠΎΠΊΠ° finally ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ Π²ΡΠΏΠ»Ρ‹Π²Π°Ρ‚ΡŒ, Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π±Π»ΠΎΠΊΠ° try станСт ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΌ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ для ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Ρ„ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ°.

Π“Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ

Π“Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ, Ссли ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊ установили, ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚ΠΈΡ‚ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, Ссли ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡŽ Ρ€Π°Π·Ρ€Π΅ΡˆΠΈΠ»ΠΈ Π²ΡΠΏΠ»Ρ‹Π²Π°Ρ‚ΡŒ Π΄ΠΎ глобальной области видимости. Ѐункция set_exception_handler() устанавливаСт callback-Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ PHP Π²Ρ‹Π·ΠΎΠ²Π΅Ρ‚ вмСсто Π±Π»ΠΎΠΊΠ° catch, Ссли Π² ΠΊΠΎΠ΄Π΅ Π½Π΅ Π²Ρ‹Π·Π²Π°Π»ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Π±Π»ΠΎΠΊΠΈ. Π­Ρ„Ρ„Π΅ΠΊΡ‚ ΠΏΠΎ сущСству Ρ‚Π°ΠΊΠΎΠΉ ΠΆΠ΅, ΠΊΠ°ΠΊ Ссли Π±Ρ‹ всю ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ ΠΎΠ±Π΅Ρ€Π½ΡƒΠ»ΠΈ Π² Π±Π»ΠΎΠΊ try-catch с этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ Π² качСствС catch.

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΡ

Π—Π°ΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅:

Π’Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ PHP Ρ‡Π°Ρ‰Π΅ ΡΠΎΠΎΠ±Ρ‰Π°ΡŽΡ‚ ΠΎΠ± ΠΎΡˆΠΈΠ±ΠΊΠ°Ρ… Ρ‡Π΅Ρ€Π΅Π· ΠΎΡ‚Ρ‡Ρ‘Ρ‚ ΠΎΠ± ΠΎΡˆΠΈΠ±ΠΊΠ°Ρ…, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ соврСмСнныС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½ΠΎ-ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ ΠΌΠΎΠ΄ΡƒΠ»ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ с ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡΠΌΠΈ. ΠŸΡ€ΠΈ этом ошибки Π»Π΅Π³ΠΊΠΎ пСрСводятся Π² ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Ρ‡Π΅Ρ€Π΅Π· класс ErrorException. Π­Ρ‚Π° Ρ‚Π΅Ρ…Π½ΠΈΠΊΠ°, ΠΎΠ΄Π½Π°ΠΊΠΎ, Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ с Π½Π΅Ρ„Π°Ρ‚Π°Π»ΡŒΠ½Ρ‹ΠΌΠΈ ошибками.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #1 ΠŸΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΎΡ‚Ρ‡Ρ‘Ρ‚ΠΎΠ² ΠΎΠ± ΠΎΡˆΠΈΠ±ΠΊΠ°Ρ… Π² ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ

<?php

function exceptions_error_handler($severity, $message, $filename, $lineno) {
throw new
ErrorException($message, 0, $severity, $filename, $lineno);
}

set_error_handler('exceptions_error_handler');

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #2 Выброс ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ

<?php

function inverse($x) {
if (!
$x) {
throw new
Exception('Π”Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° ноль.');
}
return
1 / $x;
}

try {
echo
inverse(5) . "\n";
echo
inverse(0) . "\n";
} catch (
Exception $e) {
echo
'PHP ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚ΠΈΠ» ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅: ', $e->getMessage(), "\n";
}

// ΠŸΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅
echo "ΠŸΡ€ΠΈΠ²Π΅Ρ‚, ΠΌΠΈΡ€\n";

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

0.2
PHP ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚ΠΈΠ» ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅: Π”Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° ноль.
ΠŸΡ€ΠΈΠ²Π΅Ρ‚, ΠΌΠΈΡ€

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #3 ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ Π² Π±Π»ΠΎΠΊΠ΅ finally

<?php

function inverse($x) {
if (!
$x) {
throw new
Exception('Π”Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° ноль.');
}
return
1 / $x;
}

try {
echo
inverse(5) . "\n";
} catch (
Exception $e) {
echo
'PHP ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚ΠΈΠ» ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅: ', $e->getMessage(), "\n";
} finally {
echo
"ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ Π±Π»ΠΎΠΊ finally.\n";
}

try {
echo
inverse(0) . "\n";
} catch (
Exception $e) {
echo
'PHP ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚ΠΈΠ» ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅: ', $e->getMessage(), "\n";
} finally {
echo
"Π’Ρ‚ΠΎΡ€ΠΎΠΉ Π±Π»ΠΎΠΊ finally.\n";
}

// ΠŸΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅
echo "ΠŸΡ€ΠΈΠ²Π΅Ρ‚, ΠΌΠΈΡ€\n";

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

0.2
ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ Π±Π»ΠΎΠΊ finally.
PHP ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚ΠΈΠ» ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅: Π”Π΅Π»Π΅Π½ΠΈΠ΅ Π½Π° ноль.
Π’Ρ‚ΠΎΡ€ΠΎΠΉ Π±Π»ΠΎΠΊ finally.
ΠŸΡ€ΠΈΠ²Π΅Ρ‚, ΠΌΠΈΡ€

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #4 ВзаимодСйствиС ΠΌΠ΅ΠΆΠ΄Ρƒ Π±Π»ΠΎΠΊΠ°ΠΌΠΈ finally ΠΈ return

<?php

function test() {
try {
throw new
Exception('foo');
} catch (
Exception $e) {
return
'catch';
} finally {
return
'finally';
}
}

echo
test();

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

finally

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #5 Π’Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ

<?php

class MyException extends Exception { }

class
Test {
public function
testing() {
try {
try {
throw new
MyException('foo!');
} catch (
MyException $e) {
// ΠŸΠΎΠ²Ρ‚ΠΎΡ€Π½Ρ‹ΠΉ выброс ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ
throw $e;
}
} catch (
Exception $e) {
var_dump($e->getMessage());
}
}
}

$foo = new Test;
$foo->testing();

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

string(4) "foo!"

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #6 ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ Π² ΠΎΠ΄Π½ΠΎΠΌ Π±Π»ΠΎΠΊΠ΅ catch

<?php

class MyException extends Exception { }

class
MyOtherException extends Exception { }

class
Test {
public function
testing() {
try {
throw new
MyException();
} catch (
MyException | MyOtherException $e) {
var_dump(get_class($e));
}
}
}

$foo = new Test;
$foo->testing();

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

string(11) "MyException"

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #7 ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π±Π»ΠΎΠΊΠ° catch Π±Π΅Π· ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠΉ

Π Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² PHP 8.0.0 ΠΈ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ·Π΄Π½ΠΈΡ… вСрсиях.

<?php

class SpecificException extends Exception {}

function
test() {
throw new
SpecificException('Ой!');
}

try {
test();
} catch (
SpecificException) {
print
"Ѐункция выбросила ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ SpecificException, Π½ΠΎ Π΄Π΅Ρ‚Π°Π»ΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π½Π΅Π²Π°ΠΆΠ½Ρ‹.";
}

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

Ѐункция выбросила ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ SpecificException, Π½ΠΎ Π΄Π΅Ρ‚Π°Π»ΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π½Π΅Π²Π°ΠΆΠ½Ρ‹.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #8 Throw ΠΊΠ°ΠΊ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅

Π Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² PHP 8.0.0 ΠΈ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ·Π΄Π½ΠΈΡ… вСрсиях.

<?php

function test()
{
do_something_risky() or throw new Exception('Ѐункция Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»Π°ΡΡŒ ошибкой');
}

function
do_something_risky()
{
return
false; // Π˜ΠΌΠΈΡ‚Π°Ρ†ΠΈΡ сбоя
}

try {
test();
} catch (
Exception $e) {
print
$e->getMessage();
}

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

Ѐункция Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»Π°ΡΡŒ ошибкой

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #9 Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π² Π±Π»ΠΎΠΊΠ°Ρ… try ΠΈ finally

<?php

try {
try {
throw new
Exception(message: 'Π’Ρ€Π΅Ρ‚ΡŒΠ΅', previous: new Exception('Π§Π΅Ρ‚Π²Ρ‘Ρ€Ρ‚ΠΎΠ΅'));
} finally {
throw new
Exception(message: 'ΠŸΠ΅Ρ€Π²ΠΎΠ΅', previous: new Exception('Π’Ρ‚ΠΎΡ€ΠΎΠ΅'));
}
} catch (
Exception $e) {
var_dump(
$e->getMessage(),
$e->getPrevious()->getMessage(),
$e->getPrevious()->getPrevious()->getMessage(),
$e->getPrevious()->getPrevious()->getPrevious()->getMessage(),
);
}

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

string(12) "ΠŸΠ΅Ρ€Π²ΠΎΠ΅"
string(12) "Π’Ρ‚ΠΎΡ€ΠΎΠ΅"
string(12) "Π’Ρ€Π΅Ρ‚ΡŒΠ΅"
string(18) "Π§Π΅Ρ‚Π²Ρ‘Ρ€Ρ‚ΠΎΠ΅"
οΌ‹Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΡ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ 13 notes

up
130
ask at nilpo dot com ΒΆ
17 years ago
If you intend on creating a lot of custom exceptions, you may find this code useful.  I've created an interface and an abstract exception class that ensures that all parts of the built-in Exception class are preserved in child classes.  It also properly pushes all information back to the parent constructor ensuring that nothing is lost.  This allows you to quickly create new exceptions on the fly.  It also overrides the default __toString method with a more thorough one.

<?php
interface IException
{
    /* Protected methods inherited from Exception class */
    public function getMessage();                 // Exception message 
    public function getCode();                    // User-defined Exception code
    public function getFile();                    // Source filename
    public function getLine();                    // Source line
    public function getTrace();                   // An array of the backtrace()
    public function getTraceAsString();           // Formated string of trace
    
    /* Overrideable methods inherited from Exception class */
    public function __toString();                 // formated string for display
    public function __construct($message = null, $code = 0);
}

abstract class CustomException extends Exception implements IException
{
    protected $message = 'Unknown exception';     // Exception message
    private   $string;                            // Unknown
    protected $code    = 0;                       // User-defined exception code
    protected $file;                              // Source filename of exception
    protected $line;                              // Source line of exception
    private   $trace;                             // Unknown

    public function __construct($message = null, $code = 0)
    {
        if (!$message) {
            throw new $this('Unknown '. get_class($this));
        }
        parent::__construct($message, $code);
    }
    
    public function __toString()
    {
        return get_class($this) . " '{$this->message}' in {$this->file}({$this->line})\n"
                                . "{$this->getTraceAsString()}";
    }
}
?>

Now you can create new exceptions in one line:

<?php
class TestException extends CustomException {}
?>

Here's a test that shows that all information is properly preserved throughout the backtrace.

<?php
function exceptionTest()
{
    try {
        throw new TestException();
    }
    catch (TestException $e) {
        echo "Caught TestException ('{$e->getMessage()}')\n{$e}\n";
    }
    catch (Exception $e) {
        echo "Caught Exception ('{$e->getMessage()}')\n{$e}\n";
    }
}

echo '<pre>' . exceptionTest() . '</pre>';
?>

Here's a sample output:

Caught TestException ('Unknown TestException')
TestException 'Unknown TestException' in C:\xampp\htdocs\CustomException\CustomException.php(31)
#0 C:\xampp\htdocs\CustomException\ExceptionTest.php(19): CustomException->__construct()
#1 C:\xampp\htdocs\CustomException\ExceptionTest.php(43): exceptionTest()
#2 {main}
up
78
Johan ΒΆ
15 years ago
Custom error handling on entire pages can avoid half rendered pages for the users:

<?php
ob_start();
try {
    /*contains all page logic 
    and throws error if needed*/
    ...
} catch (Exception $e) {
  ob_end_clean();
  displayErrorPage($e->getMessage());
}
?>
up
33
Edu ΒΆ
12 years ago
The "finally" block can change the exception that has been throw by the catch block.

<?php
try{
        try {
                throw new \Exception("Hello");
        } catch(\Exception $e) {
                echo $e->getMessage()." catch in\n";
                throw $e;
        } finally {
                echo $e->getMessage()." finally \n";
                throw new \Exception("Bye");
        }
} catch (\Exception $e) {
        echo $e->getMessage()." catch out\n";
}
?>

The output is:

Hello catch in
Hello finally 
Bye catch out
up
26
Shot (Piotr Szotkowski) ΒΆ
17 years ago
β€˜Normal execution (when no exception is thrown within the try block, *or when a catch matching the thrown exception’s class is not present*) will continue after that last catch block defined in sequence.’

β€˜If an exception is not caught, a PHP Fatal Error will be issued with an β€œUncaught Exception …” message, unless a handler has been defined with set_exception_handler().’

These two sentences seem a bit contradicting about what happens β€˜when a catch matching the thrown exception’s class is not present’ (and the second sentence is actually correct).
up
9
tianyiw at vip dot qq dot com ΒΆ
2 years ago
Easy to understand `finally`.
<?php
try {
    try {
        echo "before\n";
        1 / 0;
        echo "after\n";
    } finally {
        echo "finally\n";
    }
} catch (\Throwable) {
    echo "exception\n";
}
?>
# Print:
before
finally
exception
up
15
christof+php[AT]insypro.com ΒΆ
8 years ago
In case your E_WARNING type of errors aren't catchable with try/catch you can change them to another type of error like this:

<?php 
    set_error_handler(function($errno, $errstr, $errfile, $errline){
            if($errno === E_WARNING){
                // make it more serious than a warning so it can be caught
                trigger_error($errstr, E_ERROR);
                return true;
            } else {
                // fallback to default php error handler
                return false;
            }
    });

    try {
            // code that might result in a E_WARNING
    } catch(Exception $e){
            // code to handle the E_WARNING (it's actually changed to E_ERROR at this point)
    } finally {
            restore_error_handler();
    }
?>
up
16
daviddlowe dot flimm at gmail dot com ΒΆ
8 years ago
Starting in PHP 7, the classes Exception and Error both implement the Throwable interface. This means, if you want to catch both Error instances and Exception instances, you should catch Throwable objects, like this:

<?php

try {
    throw new Error( "foobar" );
    // or:
    // throw new Exception( "foobar" );
}
catch (Throwable $e) {
    var_export( $e );
}

?>
up
18
Simo ΒΆ
11 years ago
#3 is not a good example. inverse("0a") would not be caught since (bool) "0a" returns true, yet 1/"0a" casts the string to integer zero and attempts to perform the calculation.
up
20
telefoontoestel at nospam dot org ΒΆ
11 years ago
When using finally keep in mind that when a exit/die statement is used in the catch block it will NOT go through the finally block. 

<?php
try {
    echo "try block<br />";
    throw new Exception("test");
} catch (Exception $ex) {
    echo "catch block<br />";
} finally {
    echo "finally block<br />";
}

// try block
// catch block
// finally block
?>

<?php
try {
    echo "try block<br />";
    throw new Exception("test");
} catch (Exception $ex) {
    echo "catch block<br />";
    exit(1);
} finally {
    echo "finally block<br />";
}

// try block
// catch block
?>
up
6
jlherren ΒΆ
2 years ago
As noted elsewhere, throwing an exception from the `finally` block will replace a previously thrown exception. But the original exception is magically available from the new exception's `getPrevious()`.

<?php
try {
    try {
        throw new RuntimeException('Exception A');
    } finally {
        throw new RuntimeException('Exception B');
    }
}
catch (Throwable $exception) {
    echo $exception->getMessage(), "\n";
    // 'previous' is magically available!
    echo $exception->getPrevious()->getMessage(), "\n";
}
?>

Will print:

Exception B
Exception A
up
10
mlaopane at gmail dot com ΒΆ
8 years ago
<?php

/**
 * You can catch exceptions thrown in a deep level function
 */

function employee()
{
    throw new \Exception("I am just an employee !");
}

function manager()
{
    employee();
}

function boss()
{
    try {
        manager();
    } catch (\Exception $e) {
        echo $e->getMessage();
    }
}

boss(); // output: "I am just an employee !"
up
12
Tom Polomsk ΒΆ
11 years ago
Contrary to the documentation it is possible in PHP 5.5 and higher use only try-finally blocks without any catch block.
up
12
Sawsan ΒΆ
14 years ago
the following is an example of a re-thrown exception and the using of getPrevious function:

<?php

$name = "Name";

//check if the name contains only letters, and does not contain the word name

try
   {
   try
     {
      if (preg_match('/[^a-z]/i', $name)) 
       {
           throw new Exception("$name contains character other than a-z A-Z");
       }   
       if(strpos(strtolower($name), 'name') !== FALSE)
       {
          throw new Exception("$name contains the word name");
       }
       echo "The Name is valid";
     }
   catch(Exception $e)
     {
     throw new Exception("insert name again",0,$e);
     }
   }
 
catch (Exception $e)
   {
   if ($e->getPrevious())
   {
    echo "The Previous Exception is: ".$e->getPrevious()->getMessage()."<br/>";
   }
   echo "The Exception is: ".$e->getMessage()."<br/>";
   }

 ?>