Exceptions
Uit Yapf
Dit stukje code probeert duidelijk te maken hoe je de verschillende soorten foutsituaties die in een programma kunnen optreden kunt afvangen.
Het programma gaat proberen om bij een nep-database een gebruiker op te halen. Deze handeling kan (en zal) falen op meerdere manieren.
- 1: er wordt geen gebruiker opgehaald, en dat faalt dus ook niet
- 2: er wordt wel een gebruiker opgehaald en dat lukt.
- 3: er wordt een gebruiker opgehaald die niet bestaat.
- 4: er wordt een gebruiker opgehaald via een query die niet klopt.
- 5: er wordt een gebruiker opgehaald maar de database is ontploft.
Let vooral op het verschil tussen 4 en 5. Het mislukken van een query is in deze situatie geen fatale "or die" situatie. Dat het niet lukt om de gebruiker op te halen betekent precies dat: het lukt niet om de gebruiker op te halen. daarvoor hoeft niet de hele website down te zijn, net zoals je PC niet uitgeschakeld wordt als het niet lukt om aan te loggen op MSN.
Bij 5 is er wel iets griezeligs aan de hand; de hele database kan niet bereikt worden en dat betekent niet veel goeds dus dat resulteert in een exception die pas in het buitenste catch blok wordt opgevangen om te vertellen dat de website het even niet doet.
De code begint met vijf keer hetzelfde try/catch gebeuren. Deze blokken doen zich voor als vijf applicaties die elk een van de vijf situaties simuleren.
De databaseclass is volledig nep, het enige wat het doet is kijken welke user wordt opgevraagd om daarop de gewenste foutsituatie te simuleren.
<?php /** * Simuleer dat er niets aan de hand is. * */ echo '<hr/>'; echo 'Test no problemo.<br />'; try { $oApplication = new cApplication(); $oApplication->test_noproblems(); } catch (Exception $e) { echo 'De website is tijdelijk niet bereikbaar.'; } /** * Simuleer het ophalen van een gebruiker * zonder enig probleem. */ echo '<hr/>'; echo 'Test bekende user.<br />'; try { $oApplication = new cApplication(); $oApplication->test_zoekgebruiker(1); } catch (Exception $e) { echo 'De website is tijdelijk niet bereikbaar.'; } /** * Simuleer het ophalen van een gebruiker * die niet bestaat. */ echo '<hr/>'; echo 'Test onbekende user.<br />'; try { $oApplication = new cApplication(); $oApplication->test_zoekgebruiker(2); } catch (Exception $e) { echo 'De website is tijdelijk niet bereikbaar.'; } /** * Simuleer het ophalen van een gebruiker * met een fout in de query. */ echo '<hr/>'; echo 'Test foute query.<br />'; try { $oApplication = new cApplication(); $oApplication->test_zoekgebruiker(8); } catch (Exception $e) { echo 'De website is tijdelijk niet bereikbaar.'; } /** * Simuleer het ophalen van een gebruiker * terwijl de database is ontploft. */ echo '<hr/>'; echo 'Test ontplofte database.<br />'; try { $oApplication = new cApplication(); $oApplication->test_zoekgebruiker(9); } catch (Exception $e) { echo 'De website is tijdelijk niet bereikbaar.'; } /** * De applicatieclasse bevat de routines die de diverse acties uitvoeren. * */ class cApplication { protected $oDB; public function __construct() { $this->oDB = new cDB(); } public function test_noproblems() { echo 'No problemo.'; } public function test_zoekgebruiker($piUserId) { try { $oUserHandler = new cUserHandler($this->oDB); if (false === ($sUserName = $oUserHandler->getUserById($piUserId))) { echo 'De gebruiker bestaat helaas niet'; } else { echo 'Welkom ',$sUserName; } } catch (customexception_db $e) { // Als er een queryfout is dan is het (tijdelijk) niet mogelijk gebruikers op te zoeken. if (100 == $e->getCode()) { echo 'Het is tijdelijk niet mogelijk om gebruikers op te zoeken.'; } // Als de exception gaat over een ontplofte server dan gooien we de exception door. if (200 == $e->getCode()) { throw $e; } } } } /** * De userhandler regelt het ophalen van gebruikers uit de database. * */ class cUserHandler { protected $oDB; public function __construct($poDB) { $this->oDB = $poDB; } public function getUserById($piUserId) { $aResult = $this->oDB->executeQuery('SELECT foo FROM bar WHERE userid= '.$piUserId); if (count($aResult) == 0) { return false; } else { return $aResult[0]['name']; } } } /** * De databasehandler regelt het uitvoeren van queries. * * Deze implementatie is compleet nep en zorgt * alleen voor dikke paniek in de rest van de code. * * In de query wordt het userid gebruikt om te bepalen * wat voor soort ellende er wordt opgeboerd. * */ class cDB { public function executeQuery($psQuery) { /** * Fake routine om op commando een foutsituatie op te boeren. */ $iUserId = substr($psQuery,-1); switch($iUserId) { case 1: // Simuleer dat user karel is gevonden. return array(array('name'=>'Karel')); break; case 2: // Simuleer dat er geen user is gevonden. return array(); case 8: // simuleer fout in query throw new customexception_db('Syntaxfout in query', 100); break; case 9: // simuleer ontplofte databaseserver throw new customexception_db('Databaseserver onbereikbaar', 200); break; } } } /** * De customexception_db * wordt gebruikt om databaseproblemen te kunnen onderscheiden van andere soorten. */ class customexception_db extends exception { public function __construct($psMessage, $piCode) { $this->message = $psMessage; $this->code = $piCode; } } ?>