20. Fejezet. Kivételek (Exceptions)

Tartalom
Kivételek kiterjesztése

A PHP 5 kivétel modellje hasonló más programozási nyelvekéhez. Egy kivételt dobhatunk (throw) és elkaphatunk (catch) a PHP-val. A kódot try blokkba kell tenni, hogy megkönnyítsük lehetséges kivétélek kezelését. Minden try blokknak rendelkezni kell legalább egy megfelelő catch blokkal. Többszörös catch blokkokat is használhatunk, így különböző osztályú kivételeket kaphatunk el. A program (ha nincs kivétel a try blokkban, vagy ha a kivétel nem illeszkedik egy catch blokkra sem) az utolsó catch blokk után folytatódik. Kivételek dobhatóak (throw) (vagy újradobhatóak) a catch blokkban.

Ha kivételt dobtunk, a blokkban a következő kód már nem fut le, és a PHP megkeresi az első catch blokkot, amire illeszkedik a kivétel. Ha a kivételt nem sikerült elkapni, a PHP fatális hibát (Fatal Error) ad ki "Uncaught Exception ..." szöveggel, hacsak nincs a set_exception_handler() beállítva.

Példa 20-1. Kivétel küldése (throw Exception)

<?php
try
{
    
$error = 'Mindig küldd el ezt a hibát';
    
throw new Exception($error);

    
// A köv. kód már nem fut le.
    
echo 'Sose fut le';

}
catch (Exception $e) {
    echo
'Elkapott kivétel: ',  $e->getMessage(), "\n";
}

// Futás folytatása
echo 'Hello World';
?>

Kivételek kiterjesztése

A felhaszánló is hozhat létre saját kivételeket, amiket a beépített Exception osztályra kell kiterjeszteni. A tagok és tuladonságok lejjebb megmutatják, mihez lehet hozzáférni az utód osztályban, amit a beépített Exception osztálytól örököl.

Példa 20-2. A beépített Exception osztály

<?php
class Exception
{
    
protected $message = 'Unknown exception';   // kivétel üzenet
    
protected $code = 0;                        // felhasználó által megadott hibakód
    
protected $file;                            // kivétel forrásának fájlneve
    
protected $line;                            // kivétel forrásának sora

    
function __construct($message = null, $code = 0);

    
final function getMessage();                // hibaüzenet megszerzése
    
final function getCode();                   // kivétel kódja
    
final function getFile();                   // forrás fájl
    
final function getLine();                   // forrás sor
    
final function getTrace();                  // backtrace() tömb
    
final function getTraceAsString();          // formázott "trace" karakterlánc

    /* Felülírható */
    
function __toString();                       // formázott karakterlánc megjelenítéshez
}
?>

Ha az osztály utódja a beépített Exception osztálynak, és újradefinálja a konstruktort, erősen ajánlott, hogy meghívja a parent::__construct() metódust hogy biztosítsa, minden hozzáférhető adat helyesen legyen tárolva. A __toString() metódus úrjaírható, hogy tetszőleges legyen az objektum által prezentált karakterlánc.

Példa 20-3. Exception osztály kiterjesztése

<?php
/**
* Saját kivétel osztály létrehozása
*/
class MyException extends Exception
{
    
// Újradefinálás, $message nem opcinális
    
public function __construct($message, $code = 0) {
        
// Kód...
    
        // legyünk biztosak benne, hogy minden rendben tárolva
        
parent::__construct($message, $code);
    }

    
// saját __toString() függvény
    
public function __toString() {
        return
__CLASS__ . ": [{$this->code}]: {$this->message}\n";
    }

    
public function customFunction() {
        echo
"Saját függvény egy ilyen típusú kivételnek\n";
    }
}


/**
* Osztály kivétel tesztelésére
*/
class TestException
{
    
public $var;

    const
THROW_NONE    = 0;
    const
THROW_CUSTOM  = 1;
    const
THROW_DEFAULT = 2;

    function
__construct($avalue = self::THROW_NONE) {

        switch (
$avalue) {
            case
self::THROW_CUSTOM:
                
// throw custom exception
                
throw new MyException('1 is an invalid parameter', 5);
                break;

            case
self::THROW_DEFAULT:
                
// throw default one.
                
throw new Exception('2 isn\'t allowed as a parameter', 6);
                break;

            default:
                
// No exception, object will be created.
                
$this->var = $avalue;
                break;
        }
    }
}


// 1. Példa
try {
    
$o = new TestException(TestException::THROW_CUSTOM);
}
catch (MyException $e) {      // Elkapva
    
echo "Caught my exception\n", $e;
    
$e->customFunction();
}
catch (Exception $e) {        // Kihagyva
    
echo "Caught Default Exception\n", $e;
}

// Futás folytatása
var_dump($o);
echo
"\n\n";


// 2. Példa
try {
    
$o = new TestException(TestException::THROW_DEFAULT);
}
catch (MyException $e) {      // Nem ez a típus
    
echo "Caught my exception\n", $e;
    
$e->customFunction();
}
catch (Exception $e) {        // Elkapva
    
echo "Caught Default Exception\n", $e;
}

// Futás folytatása
var_dump($o);
echo
"\n\n";


// 3. Példa
try {
    
$o = new TestException(TestException::THROW_CUSTOM);
}
catch (Exception $e) {        // Elkapva
    
echo "Default Exception caught\n", $e;
}

// Futás folytatása
var_dump($o);
echo
"\n\n";


// 4. Példa
try {
    
$o = new TestException();
}
catch (Exception $e) {        // Ez nem kivétel
    
echo "Default Exception caught\n", $e;
}

// Futás folytatása
var_dump($o);
echo
"\n\n";
?>