Web Development

Ein Lehrbuch für das Informatik oder Medien-Informatik Studium.

Wir haben bisher keinerlei Rücksicht darauf genommen, dass ein Fehler auftreten könnte. Zum Beispiel könnte beim Einfügen in die Datenbank ein Constraint verletzt werden und das Einfügen fehlschlagen. Wie behandelt man diesen Fall in PHP?

Exceptions in PHP

Folgende Beschreibung ist aus dem PHP Handbuch übernommen:

PHP 5 hat ein Exceptionmodell ähnlich dem anderer Programmiersprachen. Eine Exception kann in PHP geworfen (throw) und abgefangen (catch) werden. Um das Fangen potentieller Exceptions zu ermöglichen, wird der jeweilige Code mit einem try-Block umschlossen.

Die normale Programmausführung (wenn keine Exception innerhalb des try-Blockes geworfen wird) wird nach dem letzten catch-Block fortgesetzt. Exceptions können innerhalb eines catch-Blockes geworfen (oder weitergeworfen) werden.

Wenn eine Exception geworfen wird, wird der Programmcode der auslösenden Anweisung nicht ausgeführt, und PHP versucht, den ersten passenden catch-Block zu finden. Falls eine Exception gar nicht abgefangen wird, wird ein fataler Fehler mit einer “Uncaught Exception …“-Nachricht ausgegeben

Php Code Beispiel für Exception-Handling in PHP

<?php
function compute($x) {
    if ($x == 0) {
       throw new Exception('Illegal Input: 0.');
    }
    return 1 / $x;
}

try {
    echo compute(5) . "\n";
    echo compute(0) . "\n";
} catch (Exception $e) {
    echo 'Exception abgefangen: ',  $e->getMessage(), "\n";
}

// output:
// 0.2
// Exception abgefangen: Illegal Input: 0
?>

Verwendung von Exceptions für die Datenbank

PDO wirft normalerweise keine Exceptions. Ihre Verwendung muss erst mit dem Attribut ERRMODE aktiviert werden:

  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

In folgendem Beispiel soll ein Datensatz (plus abhängige Daten) dargestellt werden. Dabei könnte schon beim Verbindungsaufbau mit der Datenbank ein Fehler auftreten, oder bei einzelnen Abfragen.

Php Code Datenbank-Abfrage mit Exception Handling als Fehlerbehandlung

$get_id = $_GET['id'];
try{
  include "config.php";

  if( ! $DSN ) {
    throw(new Exception( "DB nicht konfiguriert. config.php anlegen!" ));
  }

  $dbh = new PDO($DSN, $DB_USER, $DB_PASS);
  /* das folgende Attribut aktiviert die Exceptions */
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);

  $sth  = $dbh->prepare( "SELECT * FROM users WHERE id=?" );
  $sth->execute(array($get_id));
  $p = $sth->fetch();

  // wirklich nicht in der Datenbank
  if( $p === false ) {
    throw (new Exception( "Kein Person Nr. $get_id in der DB." ));
  }

  // Profil verborgen
  if( !$p->profile_visible  ) {
    throw (new Exception( "Kein Person Nr. $get_id in der DB." ));
  }

  $sth  = $dbh->prepare( " .... " );
  $sth->execute(array($get_id));
  $projects = $sth->fetchAll();

} catch( Exception $e ) {
  include "header.php";
  echo "<h1>Problem mit der Datenbank</h1>" ;
  echo "<p>Bitte versuchen Sie es später wieder.</p>" ;
  echo "<!--" . $e->getMessage() . "-->";
  include "footer.php";
  exit;
}

/* hier folgt die normale Ausgabe der Seite */

In diesem Beispiel erfolgt die ganze Arbeit mit der Datenbank bevor die Ausgabe beginnt. Im catch-Block wird eine Webseite erzeugt, die gar nichts mit der “normalen” Ausgabe der Seite zu tun hat.

Exkurs: Exceptions in Javascript

Die Verwendung und Schreibweise ist in Javascript so ähnlich, dass es sich gar nicht lohnt näher darauf einzugehen. Siehe Rauschmayer(2012): Ausnahmebehandlung in JavaScript in mag.js Nr.1