PHP Kokeile Catch -esimerkki: Poikkeus- ja virheenkäsittelyn opetusohjelma
⚡ Älykäs yhteenveto
PHP:n virheiden käsittely ja poikkeukset pitävät sovellukset vakaina ja turvallisina hallitsemalla odottamattomia olosuhteita paljastamatta raakoja virheitä. Tämä ohje selittää virheet ja poikkeukset, die-lausekkeet, mukautetut virheenkäsittelijät, virheraportointitasot sekä try-, throw- ja catch-poikkeusmallin useilla poikkeustyypeillä.

Mikä on poikkeus?
Virhe on odottamaton ohjelman tulos, jota ohjelma ei itse pysty käsittelemään.
Virheet korjataan korjaamalla ohjelma. Esimerkki virheestä olisi ääretön silmukka, joka ei koskaan pysähdy suorittamasta.
Poikkeus on odottamaton ohjelman tulos, jonka ohjelma itse pystyy käsittelemään.
Poikkeus on esimerkiksi tiedoston avaaminen, jota ei ole olemassa.
Tämä poikkeus voidaan käsitellä joko luomalla tiedosto tai antamalla käyttäjälle mahdollisuus etsiä tiedostoa.
Miksi käsitellä poikkeuksia?
- Vältä sivuillamme odottamattomia tuloksia, jotka voivat olla erittäin ärsyttäviä tai ärsyttäviä loppukäyttäjillemme
- Paranna sovelluksiemme turvallisuutta jättämällä paljastamatta tietoja, joita pahantahtoiset käyttäjät voivat käyttää hyökkääessään sovelluksiimme
- PHP-poikkeuksia käytetään ohjelman normaalin kulun muuttamiseen, jos tapahtuu ennustettavissa oleva virhe.
PHP-virheiden käsittely
Kun virhe tapahtuu, kokoonpanoasetuksistasi riippuen, PHP näyttää verkkoselaimessa virheilmoituksen tapahtuneeseen virheeseen liittyvillä tiedoilla.
PHP tarjoaa useita tapoja käsitellä virheitä. Tarkastelemme tässä kolmea yleisesti käytettyä menetelmää:
- Kuole lausunnot – die-funktio yhdistää echo- ja exit-funktiot. Se on erittäin hyödyllinen, kun haluamme tulostaa viestin ja pysäyttää skriptin suorituksen virheen sattuessa.
- Mukautetut virhekäsittelijät – nämä ovat käyttäjän määrittämiä toimintoja, joita kutsutaan aina virheen sattuessa.
- PHP virhe raportointi – virheilmoitus riippuu PHP-virheraportointiasetuksistasi. Tämä menetelmä on erittäin hyödyllinen kehitysympäristössä, kun et tiedä, mikä virheen aiheutti. Näytetyt tiedot voivat auttaa sinua sovelluksesi virheenkorjauksessa.
Virhe esimerkkejä käsiteltäessä
Katsotaanpa nyt joitakin yksinkertaisia esimerkkejä virheidenkäsittelyrutiineista.
Oletetaan, että meillä on laskutoimitus, joka voi jakaa luvun nollalla. Haluamme käsitellä tämän tapauksen siististi sen sijaan, että antaisimme PHP:n näyttää raakavirheen.
Alla oleva koodi toteuttaa yllä olevan esimerkin.
<?php
$denominator = 0;
echo 2 / $denominator;
?>
Olettaen, että tallensit tiedoston simple_error.php phptuts-kansioon, avaa URL http://localhost/phptuts/simple_error.php
Saat seuraavat tulokset.
Kuten yllä olevista tuloksista näet, se saa sovelluksemme näyttämään epäammattimaiselta ja voi olla ärsyttävää käyttäjälle.
Muokkaamme yllä olevaa koodia ja kirjoitamme sovellukselle virheenkäsittelijän.
<?php $denominator = 0; if ($denominator != 0) { echo 2 / $denominator; } else { echo "cannot divide by zero (0)"; } ?>
Olettaen, että tallensit yllä olevan koodin nimellä error_handling.php, avaa URL http://localhost/phptuts/error_handling.php
Huomautus: On hyvä tietoturvakäytäntö näyttää yllä olevan kaltainen viesti pelkän "Tiedostoa ei löydy" -tyyppisen viestin sijaan.
Katsotaanpa toista esimerkkiä, joka käyttää mukautettua virheenkäsittelijää.
Mukautettu virheenkäsittelijä asetetaan oletusarvoiseksi PHP-virheenkäsittelytoiminnoksi, ja se näyttää periaatteessa virhenumeron ja -viestin.
Alla oleva koodi havainnollistaa yllä olevan esimerkin toteutusta.
<?php function my_error_handler($error_no, $error_msg) { echo "Oops, something went wrong:"; echo "Error number: [$error_no]"; echo "Error Description: [$error_msg]"; } set_error_handler("my_error_handler"); echo (5 / 0); ?>
Avaa URL http://localhost/phptuts/custom_error_handler.phpSaat seuraavat tulokset.
Kuten yllä olevasta esimerkistä näet, mukautetut virheenkäsittelijät ovat tehokkaita siinä mielessä, että:
- Niiden avulla voimme mukauttaa virheilmoituksia.
- Mukautettu virheenkäsittelijä voi sisältää myös virheiden kirjaamisen tiedostoon tai tietokantaan, sähköpostin lähettämisen kehittäjälle ja vastaavia toimintoja.
Tarkastellaan nyt kolmatta virheenkäsittelytyyppiä. Käytämme PHP:n sisäänrakennettua error_reporting-funktiota. Sen perussyntaksi on seuraava.
<?php error_reporting($reporting_level); ?>
TÄSSÄ,
- "error_reporting" on PHP:n virheraportointitoiminto
- ”$reporting_level” on valinnainen ja sitä voidaan käyttää raportointitason asettamiseen. Jos raportointitasoa ei ole määritetty, PHP käyttää php.ini-tiedostossa määritettyä oletusvirheraportointitasoa.
| Raportointitaso | Tuotetiedot | esimerkki |
|---|---|---|
| E_VAROITUS | Näyttää vain varoitusviestit. Ei pysäytä käsikirjoituksen suorittamista | virhe_raportointi(E_VAROITUS); |
| HUOMAUTUS | Näyttää ilmoitukset, joita voi esiintyä ohjelman normaalin suorituksen aikana tai jotka voivat olla virhe. | virheraportointi(E_NOTICE); |
| E_USER_ERROR | Näyttää käyttäjän luomat virheet, eli mukautetun virheenkäsittelijän | virheraportointi(KÄYTTÄJÄVIRHE); |
| E_USER_WARNING | Näyttää käyttäjien luomat varoitusviestit | error_reporting(E_USER_WARNING); |
| E_USER_NOTICE | Näyttää käyttäjien luomat ilmoitukset | error_reporting(E_USER_NOTICE); |
| E_RECOVERABLE_ERROR | Näyttää virheet, jotka eivät ole kohtalokkaita ja jotka voidaan käsitellä mukautetuilla virheenkäsittelijöillä | virheen_raportointi(E_RECOVERABLE_ERROR); |
| E_ALL | Näyttää kaikki virheet ja varoitukset | virheraportointi(E_ALL); |
Ero virheiden ja poikkeuksien välillä
- Poikkeuksia heitetään ja ne on tarkoitus napata, kun taas virheitä ei yleensä voida korjata.
- Poikkeukset käsitellään oliopohjaisesti. Tämä tarkoittaa, että kun poikkeus heitetään, luodaan poikkeusobjekti, joka sisältää poikkeuksen tiedot.
Alla oleva taulukko näyttää poikkeusobjektien metodit.
| Menetelmä | Tuotetiedot | esimerkki |
|---|---|---|
| getMessage() | Näyttää poikkeuksen viestin |
<?php
echo $e->getMessage();
?>
|
| saadaCode() | Näyttää poikkeusta edustavan numerokoodin |
<?php
echo $e->getCode();
?>
|
| getFile() | Näyttää tiedostonimen ja polun, jossa poikkeus tapahtui |
<?php
echo $e->getFile();
?>
|
| getLine() | Näyttää rivinumeron, jolla poikkeus tapahtui |
<?php
echo $e->getLine();
?>
|
| saadaTrace() | Näyttää selkänojan taulukontrace ennen poikkeusta |
<?php print_r( $e->getTrace()); ?> |
| getPrevious() | Näyttää edellisen poikkeuksen ennen nykyistä |
<?php
echo $e->getPrevious();
?>
|
| saadaTraceAsString() | Näyttää takaosantracpoikkeuksen e merkkijonona taulukon sijaan |
<?php
echo $e->getTraceAsString();
?>
|
| __toString() | Näyttää koko poikkeuksen merkkijonona |
<?php
echo $e->__toString();
?>
|
Alla on perussyntaksi poikkeuksen heittämiseen.
<?php throw new Exception("This is an exception example"); ?>
TÄSSÄ,
- "heittää" on avainsana, jota käytetään heittämään poikkeus
- ”new Exception(…)” luo poikkeusobjektin ja välittää viestiparametrina merkkijonon ”Tämä on poikkeusesimerkki”.
Yllä oleva koodi tulostaa seuraavan viestin.
Tarkastelemme nyt esimerkkiä, joka toteuttaa throw- ja catch-poikkeukset. Muokkaamme yllä olevaa esimerkkiä ja lisäämme siihen try-, throw- ja catch-poikkeukset.
Siinä on seuraava perussyntaksi.
<?php try { // code goes here that could potentially throw an exception } catch (Exception $e) { // exception handling code goes here } ?>
TÄSSÄ,
- "try{…}" on suoritettava koodilohko, joka saattaa aiheuttaa poikkeuksen
- "catch(Exception $e){…}" on koodilohko, joka saa kiinni heitetyn poikkeuksen ja määrittää poikkeusobjektin muuttujalle $e.
Alla oleva koodi näyttää peruspoikkeuksen esimerkin, jossa on toteutettu try-, throw- ja catch-operaattorit. Ohjelma heittää tarkoituksella poikkeuksen, jonka se sitten nappaa.
<?php try { $var_msg = "This is an exception example"; throw new Exception($var_msg); } catch (Exception $e) { echo "Message: " . $e->getMessage(); echo ""; echo "getCode(): " . $e->getCode(); echo ""; echo "__toString(): " . $e->__toString(); } ?>
Avaa URL http://localhost/phptuts/exception_handling.phpSaat seuraavat tulokset.
On myös mahdollista luoda useita poikkeuksia yhdelle PHP try -lausekkeelle riippuen heitetyn poikkeuksen tyypistä.
Katso artikkeli aiheesta MySQL, PHP-tietojen käyttö useiden poikkeusten toteutusesimerkkejä varten.
Useita poikkeuksia
Useat poikkeukset käyttävät useita catch-lohkoja heitettyjen poikkeusten käsittelyyn. Useat poikkeukset ovat hyödyllisiä, kun:
- Haluat näyttää mukautetun viestin heitetyn poikkeuksen mukaan
- Haluat suorittaa ainutlaatuisen toiminnon heitetyn poikkeuksen mukaan
Alla oleva vuokaavio havainnollistaa, miten useat poikkeukset toimivat.
Tarkastellaan esimerkkiä, joka käyttää useita poikkeuksia. Muokkaamme koodia, joka jakaa luvun syötetyllä nimittäjällä.
Odotamme kahdenlaisia poikkeuksia:
- Nollalla jakaminen
- Jako negatiivisella luvulla
Yksinkertaisuuden vuoksi näytämme catch-lohkoissamme vain poikkeustyypin. PHP:n sisäänrakennettua Exception-luokkaa käytetään poikkeusten heittämiseen. Luomme kaksi luokkaa, jotka laajentavat Exception-luokkaa ja käyttävät niitä poikkeusten heittämiseen.
Alla oleva koodi näyttää toteutuksen.
<?php class DivideByZeroException extends Exception {}; class DivideByNegativeException extends Exception {}; function process($denominator) { try { if ($denominator == 0) { throw new DivideByZeroException(); } else if ($denominator < 0) { throw new DivideByNegativeException(); } else { echo 25 / $denominator; } } catch (DivideByZeroException $ex) { echo "DIVIDE BY ZERO EXCEPTION!"; } catch (DivideByNegativeException $ex) { echo "DIVIDE BY NEGATIVE NUMBER EXCEPTION!"; } catch (Exception $x) { echo "UNKNOWN EXCEPTION!"; } } process(0); ?>
Koodin testaus
Oletetaan, että tallensit multiple_exceptions.php-tiedoston phptuts-kansioon.
Selaa URL http://localhost/phptuts/multiple_exceptions.php
Vaihda takaisin PHP-tiedostoon ja anna -1 parametriksi seuraavan kaavion mukaisesti.
Selaa URL http://localhost/phptuts/multiple_exceptions.phpMitä tuloksia saat? Anna nyt parametriksi 3. Mitä tuloksia saat?
Finally Block ja PHP 7 -virhemalli
Moderni PHP lisää yllä olevaan malliin kaksi tärkeää osaa. Finally-lohko suoritetaan try- ja catch-komentojen jälkeen riippumatta siitä, heitettiinkö poikkeus, mikä tekee siitä ihanteellisen siivoukseen, kuten tiedoston tai tietokantayhteyden sulkemiseen.
PHP 7:stä lähtien monet aiemmat kohtalokkaat virheet on heitetty Error-objekteina. Sekä Exception että Error toteuttavat Throwable-rajapinnan, joten catch (\Throwable $e) -lohko voi käsitellä kumman tahansa.
<?php try { $result = 10 / 0; } catch (DivisionByZeroError $e) { echo "Caught: " . $e->getMessage(); } finally { echo "This message always runs"; } ?>
Tässä nollalla jakaminen aiheuttaa DivisionByZeroError-virheen PHP 8:ssa, catch-lohko raportoi siitä ja finally-lohko suoritetaan aina tulostaen viestinsä siitä, tapahtuiko virhe vai ei.








