Claudiu Persoiu

Blog-ul lui Claudiu Persoiu


Archive for the ‘finally’ tag

Finally finally in PHP 5.5

with one comment

Cea mai noua versiune de PHP este aproape gata. In momentul cand scriu acest blog, PHP 5.5 este in RC 1.

Cum am mai spus si in blogul anterior, lista de noutati este disponibila la: http://www.php.net/manual/en/migration55.new-features.php

Al doilea feature ca popularitate este “finally”: http://www.php.net/manual/en/language.exceptions.php

Care-i treaba cu “finally“?

Pare un pic confuz, pare un bloc care se executa dupa ce se termina blocul de try catch. Dar ce este nou?

Sa zicem ca avem un bloc try/catch:

PHP 5.x < 5.5:

// open resouce
$resource = new Resouce();
try {
    // do stuff with the resouce
    $resouce->doStuff();
} catch (Exception $e) {
    // log exception
    syslog(LOG_ERR, $e->getMessage());
}
// release resouce
unset($resouce);

PHP 5.5

// open resouce
$resource = new Resouce();
try {
    // do stuff with the resouce
    $resouce->doStuff();
} catch (Exception $e) {
    // log exception
    syslog(LOG_ERR, $e->getMessage());
} finally {
    // release resouce
    unset($resouce);
}

Pana aici nu exista nici un motiv pentru care este nevoie de un nou bloc. Am prins exceptia, am facut logging pe ea si am continuat.

Dar sa zicem ca este o resursa si vrem sa o eliberam, iar ulterior sa aruncam exceptia. O varianta ar fi sa eliberam resursa in catch.

Dar mai ramane cazul “fericit”, sa zicem ca trebuie sa o eliberam si atunci.

// open resouce
$resource = new Resouce();
try {
    // do stuff with the resouce
    $resouce->doStuff();
} catch (Exception $e) {
    // release resouce
    unset($resource);
    // perpetuate exception
    throw $e;
}

Sa complicam si mai mult, sa zicem ca avem n tipuri de exceptii. Vor rezulta n conditii de catch, plus 1 pentru cazul fericit, iar in toate trebuie sa eliberam resursa. Nu foarte eficient…

O alta varianta este sa stocam exceptia intr-o variabila si, dupa ce am eliberat resursa, sa aruncam si exceptia, daca este cazul.

// variable to store the exception
$exception = false;

// open resouce
$resource = new Resouce();
try {
    // do stuff with the resouce
    $resouce->doStuff();
} catch (Exception $e) {
    $exception = $e;
}

// release resouce
unset($resource);

if($exception) {
    throw $exception;
}

Acesta este unul din modurile in care se realizeaza in prezent. Functioneaza, dar nu evidentiaza faptul ca poate doar vrem sa eliberam resursa si sa ne continuam viata in liniste.

Varianta PHP 5.5

In manualul php.net:

In PHP 5.5 and later, a finally block may also be specified after the catch blocks. Code within the finally block will always be executed after the tryand catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.

De fiecare data cand blocul se executa, indiferent daca se executa cu succes sau nu, finally se va executa. Deci, pentru exemplul:

try {
     echo 'Do stuff' . PHP_EOL;
     throw new Exception('testing');
} finally {
     echo 'inside finally' . PHP_EOL;
}

Outputul va fi:

Do stuff
inside finally

Fatal error: Uncaught exception 'Exception' with message 'testing' in...

Daca vrem sa prindem si exceptia:

try {
     echo 'Do stuff' . PHP_EOL;
     throw new Exception('testing');
} catch (Exception $e) {
     echo 'do something with the exception' . PHP_EOL;
} finally {
     echo 'inside finally' . PHP_EOL;
}

Outputul va fi:

Do stuff
do something with the exception
inside finally

Si chiar daca luam cazul si mai particular, cand prindem exceptia, apoi o aruncam:

try {
     echo 'Do stuff' . PHP_EOL;
     throw new Exception('testing');
} catch (Exception $e) {
     echo 'do something with the exception' . PHP_EOL;
     throw $e;
} finally {
     echo 'inside finally' . PHP_EOL;
}

Pare ca acum am reusit sa prevenim executia blocului finally? Nu este tocmai asa…

Do stuff
do something with the exception
inside finally

Fatal error: Uncaught exception 'Exception' with message 'testing' in...

Cu alte cuvinte, blocul finally se executa de fiecare data, indiferent de rezultat.

Written by Claudiu Persoiu

19 May 2013 at 7:34 PM

Posted in PHP

Tagged with , ,