# PHP 5 – Was ist neu?

Bevor das Alte untergeht, sieht man das Neue marschbereit.
Endry Andy (1877–1919), ungarischer Dichter und Lyriker

Die neue PHP-Version ist seit ein paar Wochen verfügbar, und mittlerweile folgte auch ein Update auf die Version 5.0.1, die einige Bugfixes enthält. Anstatt die neuen Funktionen von PHP 5 direkt in den vorangegangen Kapiteln unterzubringen, fanden sie nun in diesem eigenen Kapitel Platz. Der Grund ist, dass die meisten Provider, bei denen Sie einen Account anmieten können, frühestens Ende des Jahres 2004 auf PHP 5 umstellen werden. Zuvor müssen Evaluierungen und Kompatibilitätstests stattfinden, um eine reibungslose Zusammenarbeit mit anderen Komponenten des Webservers zu gewährleisten. Versuchen Sie also erst einmal, Ihre Projekte mit PHP 4 umzusetzen und erst, wenn Ihr Provider PHP 5 bietet, auf die neuen Funktionen zurückzugreifen.

# Objektorientierung

Objektorientierte Ansätze existieren schon seit langem in PHP. Es lassen sich neue Klassen mit Eigenschaften und Methoden definieren, und auch Vererbung ist möglich. Darüber hinaus fehlen jedoch viele wichtige Elemente der objektorientierten Programmierung. Dem haben sich die Zend-Entwickler angenommen und die Objektorientierung in PHP stark erweitert. Dies geschah mit Sicherheit auch, weil viele Entwickler diese halbherzige Umsetzung als größten Kritikpunkt angeführt haben.

Was aus der OOP bisher fehlte, war die Möglichkeit, den Zugriff auf Eigenschaften und Methoden beschränken zu können. Diese Beschränkung hat den Vorteil, dass Sie Variablen und Funktionen sperren können, die nur innerhalb der Klasse genutzt werden dürfen. Sobald also ein Objekt der Klasse instanziiert wird, kann die Eigenschaft nicht mehr ausgelesen oder geschrieben werden und die Funktion nicht ausgeführt werden. So wird eine fehlerhafte Nutzung einer Klasse unterbunden und der Code wird robuster.

Um diese Beschränkungen festlegen zu können, werden bei der Deklaration von Variablen und Funktionen bestimmte Schlüsselwörter vorangestellt, die den Zugriff auf die Eigenschaft oder Methode definieren.

  • public
    Eine mit public deklarierte Variable oder Funktion ist immer zugänglich, d. h., die Variable darf gelesen und geschrieben werden und die Funktion darf aufgerufen werden. Dies gilt sowohl für ein auf dieser Klasse basierendes Objekt, als auch für eine Klasse, die von dieser Klasse abgeleitet wurde.
  • protected
    Das Schlüsselwort protected legt fest, dass auf diese Variable oder Funktion nur innerhalb dieser oder abgeleiteter Klassen zugegriffen werden kann. Wurde ein Objekt von der Klasse instanziiert, ist der Zugriff auf die entsprechende Eigenschaft oder Methode nicht möglich.
  • private
    Deklarieren Sie eine Variable oder Funktion als private, kann nur in der ursprünglichen Klasse darauf zugegriffen werden. Weder in einer abgeleiteten Klasse noch als Objekt kann darauf zugegriffen werden.

Aus Kompatibilitätsgründen zu früheren PHP-Versionen ist – wenn keines der anderen Schlüsselwörter angegeben wurde – public die Standardeinstellung für Variablen und Funktionen einer Klasse.

Testen Sie einmal das folgende Listing:

<?php

  class protection
  {
    public $strPublic = 'public property';
    protected $strProtected = 'protected property';
  }
  
  $objProt = new protection;
  
  echo $objProt->strPublic.'<br>';
  echo $objProt->strProtected.'<br>';
  
?>

Listing 10.1: Test für public und protected Variablen

Den Wert der Eigenschaft strPublic wird Ihnen PHP noch ausgeben, aber spätestens bei dem Versuch, strProtected auszugeben, bricht der Interpreter mit einem Fatal Error ab. Das Gleiche würde natürlich gelten, wenn Sie versuchen, eine Methode, die als protected deklariert wurde, aufzurufen. In diesem Fall bricht der Interpreter ebenfalls ab. Ein Beispiel:

<?php

  class protection
  {
    public function publicText()
    {
      echo 'public<br>';
    }
    protected function protectedText()
    {
      echo 'protected<br>';
    }
  }
  
  $objProt = new protection;
  
  echo $objProt->publicText();
  echo $objProt->protectedText();
  
?>

Listing 10.2: Test für public und protected Methoden

Exakt so verhält es sich selbstverständlich auch mit Eigenschaften und Methoden, die als private deklariert wurden. Auch hier bricht der Interpreter bei dem Versuch ab, entweder lesend oder schreibend auf die Eigenschaft zuzugreifen oder eine entsprechende Methode auszuführen. Darüber hinaus würde auch der Versuch, eine solche Eigenschaft oder Methode in einer abgeleiteten Klasse zu erben, unterbunden werden.

# Konstruktor und Destruktor

Jede Klasse verfügt in der Regel über einen Konstruktur. Bei der Instanziierung eines Objekts können Sie dem Konstruktor Parameter übergeben, mit denen grundlegende Eigenschaften des Objekts festgelegt werden können.

In vorangegangenen Versionen wurde der Konstruktor für eine Klasse definiert, indem innerhalb der Klasse eine Funktion mit dem gleichen Bezeichner wie der Klasse notiert wurde.

<?php
  class constructor_test
  {
    /* Konstruktor der Klasse constructor_test */
    function constructor_test($aValue)
    {
      echo $aValue;
    }
  }
?>

Listing 10.3: Definition eines Konstruktors in PHP vor Version 5

Das ließ sich sehr leicht merken, hatte jedoch einen enormen Nachteil. Denn was passiert, wenn die Klasse umbenannt wird? Dann muss die Funktion, die als Konstruktor dienen soll, ebenfalls umbenannt werden. Das kann, falls man es einmal vergessen hat, eine nervenaufreibende Angelegenheit werden. Deshalb wurde in PHP 5 ein Standardbezeichner für Konstruktoren eingeführt:

__construct

Schauen Sie bei dem Bezeichner einmal genauer hin: Es sind zwei Unterstriche, mit denen der Bezeichner eingeleitet wird. Dies kann eine Fehlerquelle sein und sollte bei der Fehlersuche unbedingt berücksichtigt werden.

Das vorangegangene Beispiel der Klasse mit Konstruktor würde in PHP 5 folgendermaßen definiert werden:

<?php

  class constructor_test
  {
    /* Konstruktor der Klasse constructor_test */
    function __construct($aValue)
    {
      echo $aValue;
    }
  }

?>

Listing 10.4: Definition eines Konstruktors ab PHP Version 5

Außer durch die Bezeichnung unterscheiden sich die beiden Konstruktoren nicht voneinander. Die Handhabung und der Zeitpunkt, zu dem sie ausgeführt werden, bleiben gleich.

Die alte Variante, also eine Funktion dem gleichen Bezeichner wie dem der Klasse zu definieren, funktioniert aus Kompatibilitätsgründen auch immer noch in PHP 5. Sie müssen also Ihre vorhandenen Klassen nicht für PHP 5 umprogrammieren.

Neu hinzugekommen ist jedoch der Destruktor, der auch in allen anderen objektorientierten Programmiersprachen hinlänglich bekannt ist. Dieser wird immer dann aufgerufen, wenn ein Objekt aufgelöst werden soll. Nun werden in PHP Objekte selten von Hand aufgelöst, sondern bis zum Ende des Skripts beibehalten, da sie schlussendlich vom PHP-Interpreter gelöscht werden und der von Ihnen belegte Speicher wieder freigegeben wird.

Es gibt jedoch durchaus Gründe, die für einen Destruktor sprechen. Einmal angenommen, Sie instanziieren gleich zu Beginn Ihres Skripts ein Objekt einer Klasse, deren Aufgabe darin besteht, eine CSV-Datei vollständig einzulesen und die Daten in aufbereiteter Form bereit zu halten, so dass Sie schnell und direkt auf diese zugreifen können. Während des Ablaufs des Skripts werden Änderungen an den Daten vorgenommen, die unbedingt gespeichert werden müssen. Normalerweise würde der Interpreter am Ende des Skripts das Objekt löschen. Würden Sie die Daten nicht speichern, sind die vorgenommenen Änderungen verloren.

Anders liegt der Fall jedoch, wenn Sie für die Klasse einen Destruktor definiert haben. Da dieser immer vor dem Auflösen eines Objekts aufgerufen wird, können Sie dort Anweisungen notieren, die die vorgenommenen Änderungen in einer Datei speichern. Die Daten sind gerettet, und der möglicherweise entstehende Frust, weil Sie vergessen haben, die Methode zum Sichern der Daten manuell aufzurufen, entsteht erst gar nicht.

Um einen Destruktor zu definieren, müssen Sie innerhalb der Klasse einfach eine Funktion mit dem Bezeichner __destruct notieren. Denken Sie auch hier daran, zwei Unterstriche aufzuschreiben.

Ein kurzes Beispiel für einen Destruktor

<?php

  class destructor_test
  {
    /* Konstruktor der Klasse destructor_test */
    function __construct($aValue)
    {
      echo $aValue.'<br>';
    }

    /* Destruktor der Klasse destructor_test */
    function __destruct($aValue)
    {
      echo 'Objekt wird gelöscht';
    }
  }

?>

Listing 10.5: Konstruktor und Destruktor in einer Klasse

mit einem Beispieleinsatz der Klasse

<?php

  include('destructor_test.class.php');
  $test = new destructor_test('Ich wurde vom Konstruktor ausgegeben');

?>

Listing 10.6: Beispiel für die Nutzung der Klasse aus Listing 10.5

und der Ausgabe:

Ich wurde vom Konstruktor ausgegeben
Objekt wird gelöscht

Zugegeben, das Beispiel ist keineswegs praxistauglich, jedoch verdeutlich es die Definition und den Zweck von Konstruktoren und Destruktoren.

# Fehlerbehandlung

Fehlermeldungen gehören zum Alltag des Programmierers, wie überhöhte Benzinkosten zu dem eines Autofahrers. Beides kostet Nerven und führt dazu, dass man immer über die anderen flucht. Programmierer können jedoch Abhilfe schaffen.

Um in PHP etwaige Fehlermeldungen zu unterdrücken, wird häufig und gern der @-Operator einer Funktion vorangestellt. Anstatt also diese Meldungen dem Anwender zu präsentieren, werden sie sang- und klanglos ins Abseits geschickt. Dies ist die unsauberste aller möglichen Methoden. Denn wenn eine schwerwiegende Meldung dabei ist, erhält man selten Rückmeldung darüber, falls man nicht regelmäßig in irgendwelchen Protokollen nachsieht.

Die sauberste und beste Variante, die es gibt, besteht darin, die Fehler aufzufangen und entsprechende Meldungen auszugeben und unter Umständen auch den Programmablauf zu unterbrechen, damit kein Schaden angerichtet wird. Völlig unverständlich war deshalb, warum die Entwickler von Zend nicht die gebräuchlichste aller Formen in PHP zur Verfügung gestellt haben: try..catch. Selbst in JavaScript steht Ihnen diese Art der Fehlerbehandlung zur Verfügung.

# Die herkömmlichen Varianten

Die Anwendung von so genannten try..catch-Blöcken ist einfach. Im try-Anweisungsblock werden Anweisungen notiert, die zu einer Fehlermeldung führen könnten. Sollte eine der aufgerufenen Funktionen nun einen Fehler verursachen, springt der PHP-Interpreter in den catch-Anweisungsblock, und eine Verarbeitung mit Ausgabe einer korrekten Fehlermeldung kann erfolgen.

Gehen Sie einmal davon aus, dass Sie eine Klasse definiert und diese in einer separaten Datei gespeichert haben, um diese Klasse in beliebigen Projekten einsetzen zu können. Damit die Klasse zur Verfügung steht, müssen Sie sie einbinden:

<?  
  include('meine_super_klasse.inc.php');  
?>

Was passiert, wenn diese Datei gar nicht existiert? Richtig, PHP gibt Ihnen unschöne Fehlermeldungen aus. Da Sie den @-Operator kennen, nutzen Sie ihn vorsichtshalber.

<?  
  @include('meine_super_klasse.inc.php');  
?>

PHP erkennt zwar, dass die Datei nicht existiert und kann diese auch nicht finden, doch statt die Fehlermeldungen auszugeben, werden sie einfach ignoriert. Wird die Klasse jedoch zur Ausführung benötigt und wird versucht, ein Objekt auf Basis dieser Klasse zu instanziieren, sind weitere Fehlermeldungen die Folge. Anstatt nun vor jede erdenkliche Funktion ein @ zu schreiben, möchten Sie es etwas eleganter lösen:

<?php  
  if(!@include('meine_super_klasse.inc.php'))  
  {  
    die('Die Klasse <b>meine_super_klasse.inc.php</b> konnte nicht   
         eingebunden werden!');  
  }  
?>

Die Lösung ist zu überprüfen, ob die Datei eingebunden werden konnte. Wenn das nicht möglich war, wird mit die die Ausführung abgebrochen und eine Meldung ausgegeben. Mit PHP 4.x ist dies mehr oder minder die beste Lösung, die Sie finden können, und für diese Aufgabe funktioniert sie auch tadellos.

So weit, so schlecht! Denn wenn Sie die Situation ein wenig verändern, ist die Lösung mit die nicht mehr die beste. Angenommen, Sie haben eine Klasse definiert, die Dateien einlesen soll, deren Namen und Pfade als Parameter übergeben werden, z. B. eine CSV-Datei. Die Datei soll geöffnet werden, wird nicht gefunden, und Sie brechen den PHP-Prozess auf der Stelle mit die ab. Selbst das Skript, das Ihre Klasse benutzen möchte, wird an der weiteren Ausführung gehindert, und möglicherweise führt dies zu einem Datenverlust, weil das Hauptskript nicht mehr die Möglichkeit zum Sichern bekam. Sie könnten natürlich bestimmte Verfahrensweisen festlegen, die den Aufrufer informieren, dass die Ausführung nicht geklappt hat, z. B. durch die Rückgabe des Wertes false und einer Klassenvariablen, in der Sie Fehlermeldungen ablegen. So etwas kann aber ausarten, und ehe Sie sich versehen, besteht Ihre Klasse eigentlich nur noch daraus, dass etwaige Fehler überprüft und behandelt werden.

# Die elegante Lösung

Mit try..catch-Blöcken haben Sie diese Probleme nicht mehr. Im Gegenteil, die Fehlerbehandlung wird zu einer leichten übersichtlichen Übung, die zudem flexibel gestaltet werden kann.

Nehmen wir das include-Beispiel aus dem vorangegangenen Kapitel.

<?php

  $filename = 'meine_super_klasse.inc.php';
  
  try
  {
    if(file_exists($filename))
    {
      include($filename);
    }
    else
    {
      throw new Exception("Die Datei $filename existiert nicht!");
    }
  }
  catch(Exception $e)
  {
    echo $e->getMessage();
  }

?>

Listing 10.7: Fehlerbehandlung mit try und catch

Innerhalb des try-Anweisungsblocks wird zunächst einmal mit file_exists überprüft, ob die Datei überhaupt existiert. Ist dies der Fall, wird sie mit include eingebunden. Sollte die Datei nicht existieren, kommt der neue Ansatz in PHP 5 zum Tragen.

Im else-Anweisungsblock »wirft« der Befehl throw in diesem Fall eine Fehlermeldung ab. Dazu wird mit new ein neues Objekt der Klasse Exception erzeugt und dem Konstruktor der Klasse der eigentliche Fehlertext übergeben.

Die Definition des catch-Anweisungsblocks besagt Folgendes: Alle mit throw ausgelösten Fehlerobjekte, die auf der Klasse Exception basieren, sollen aufgefangen werden. Als Bezeichner für die Objekte wird $e verwendet. Innerhalb des Anweisungsblocks können Sie nun auf die Fehler reagieren, z. B. indem Sie die Meldung des ausgelösten Fehlers ausgeben. Dazu verfügt das Objekt $e (basierend auf der Klasse Exception) über die Methode getMessage, die den Text zurückgibt.

Natürlich können Sie stattdessen auch andere Routinen als die einfache Ausgabe der Meldung notieren, z. B. eine Suche nach der Datei oder Ähnliches.

Das nachfolgende Beispiel demonstriert, wie Sie throw in Ihren Klassen einsetzen können.

<?php

  class csv
  {
    function __construct($strFilename)
    {
      if(file_exists($strFilename))
      {
        // Datei laden
      }
      else
      {
        throw new Exception("Die Datei <b>$strFilename</b> existiert nicht!");
      }
    }

    /* weitere Methoden */  
  }
  
  try
  {
    $csv = new csv('test.csv');
  }

  catch(Exception $e)
  {
    $e->getMessage();
  }
  
?>

Listing 10.8: Fehlerbehandlung mit try und catch in Klassen

Die Klasse csv aus dem Beispiellisting ist nicht vollständig, was zur Verdeutlichung aber auch nicht notwendig ist. Im Konstruktor der Klasse wird überprüft, ob die übergebene Datei überhaupt existiert. Falls nicht, wird ein Fehler mit einer entsprechenden Meldung ausgelöst. Im Hauptteil des Skripts werden mögliche ausgelöste Fehler durch die try- und catch-Anweisungsblöcke behandelt.

# Eigene Fehlertypen

Es ist möglich, zu einem try-Anweisungsblock mehrere catch-Anweisungen zu notieren. Dies mag im ersten Moment wenig nutzbringend erscheinen. Jedoch können Sie auch eigene Fehlertypen definieren und so auf unterschiedliche Fehlertypen auch unterschiedlich reagieren.

Die erste Möglichkeit wäre, eine eigene Klasse zu definieren, die Ihnen zum Beispiel die Möglichkeit bietet, mehr Informationen zu übergeben. So könnte diese neben dem Fehlertext auch eine Fehlernummer entgegennehmen.

<?php

  class DetailedException
  {
    private $intErrNo;
    private $strError;
    
    function __construct($intErrNo,$strError)
    {
      $this->$intErrNo = $intErrNo;
      $this->$strError = $strError;
    }
    
    function getMessage()
    {
      return $this->strError;
    }
    
    function getNumber()
    {
      return $this->intErrNo;
    }
  }
  
?>

Listing 10.9: Eigene Exceptions definieren

Die Klasse DetailedException nimmt im Konstruktor die Parameter $intErrNo und $strError entgegen und weist sie den privaten Eigenschaften intErrNo und strError zu. Zusätzlich verfügt die Klasse über zwei Funktionen, die einmal den Fehlertext und einmal die Fehlernummer zurückgeben.

Der Einsatz der Klasse ist einfach:

<?php

  /* Klasse einbinden */
  include('DetailedException.class.php');
  
  /* Datei laden */
  try
  {
    if(file_exists('test.csv'))
    {
      // Hier wird die Datei geladen
    }
    else
    {
      throw new DetailedException(101,'Datei <b>test.csv</b> existiert nicht!');
    }
  }
  /* Fehler des Typs DetailedException */
  catch(DetailedException $e)
  {
    echo 'Fehler '.$e->getNumber().': '.$e->getMessage();
  }
  /* Fehler des Typs Exception */
  catch(Exception $e)
  {
    echo $e->getMessage();
  }  

?>

Listing 10.10: Selbst definierte Exceptions verwenden

Die Klasse DetailedException ließe sich natürlich noch beliebig erweitern, und auch der Einsatz innerhalb des catch-Anweisungsblocks kann so je nach Erweiterung variieren.

Sie können aber auch von der eigentlichen Klasse Exception neue Klassen ableiten. Dies macht vor allem dann Sinn, wenn Sie lediglich den Fehler stärker typisieren möchten, damit die Fehler individueller behandelt werden können.

<?php

  class FileException extends Exception
  {
    function __construct($strMessage)
    {
      parent::__contruct('FileException: '.$strMessage);
    }
  }
  
?>

Listing 10.11: Neue Exceptions auf Basis der Klasse Exception

Der einzige Unterschied der Klasse FileException zu Exception besteht in der Bezeichnung der Klasse und darin, dass dem eigentlichen Fehlertext noch eine Meldung vorangestellt wird. Der größte Unterschied zwischen beiden Klassen ist jedoch die Art, wie sie eingesetzt werden.

<?php

  /* Klasse einbinden */
  include('FileException.class.php');
  
  /* Datei laden */
  try
  {
    if(file_exists('test.csv'))
    {
      // Hier wird die Datei geladen
    }
    else
    {
      throw new FileException('Datei <b>test.csv</b> existiert nicht!');
    }
  }
  /* Fehler des Typs FileException */
  catch(FileException $e)
  {
    // Anweisungen zum Suchen der Datei
    echo $e->getMessage();
  }
  /* Fehler des Typs Exception */
  catch(Exception $e)
  {
    echo $e->getMessage();
  }  

?>

Listing 10.12: Typisierte Exceptions einsetzen

Mit dieser Art der Fehlertypisierung können Sie natürlich beliebig fortfahren. Sie können eigene Klassen für unterschiedlichste Fehler definieren. Wenn Sie bereits Erfahrung in Programmiersprachen wie C/C++/Java oder auch Delphi haben, wird Ihnen dies bei Ihrem Umstieg auf PHP sicherlich hilfreich sein.

Grundsätzlich müssten Sie für eine typisierte Exception nicht unbedingt den Konstruktor neu definieren. Jedoch wird in der Klasse FileException der Fehlermeldung noch ein Text vorangestellt, wodurch ein Überschreiben notwendig ist.

# SimpleXML

In PHP 4 war es teilweise recht umständlich, XML-Dokumente zu verarbeiten, ob nun lesend oder schreibend. Dies hat sich in PHP 5 außerordentlich verbessert, da nun als Grundlage eine andere Bibliothek verwendet wird: SimpleXML (http://www.libxml.org).

Bei genauerer Betrachtung sind XML-Dokumente nichts weiter als eine Baumstruktur mit mal mehr und mal weniger Verästelungen. Solche Baumstrukturen lassen sich problemlos als Array oder auch Objekte darstellen, und genau diesen Weg verfolgt SimpleXML.

Als Grundlage wird das folgende XML-Dokument verwendet. Es basiert auf einer gleichmäßigen Datenstruktur und kann in dieser Form als Datenbanktabelle betrachtet werden.

<?xml version="1.0"?>
<buecher>
    <buch>
        <titel>Webseiten programmieren und gestalten</titel>
        <autor>Mark Lubkowitz</autor>
        <auflage>1</auflage>
        <isbn>3–89842–313–1</isbn>
    </buch>
    <buch>
        <title>Einstieg in MySQL</titel>
        <autor>Mark Lubkowitz</autor>
        <auflage>1</auflage>
        <isbn>3–89842–427–8</isbn>
    </buch>
    <buch>
        <titel>Webseiten programmieren und gestalten</titel>
        <autor>Mark Lubkowitz</autor>
        <auflage>2</auflage>
        <isbn>3–89842–557–6</isbn>
    </buch>
</buecher>

Listing 10.13: Beispiel für ein XML-Dokument

Dieses XML-Dokument enthält insgesamt drei Datensätze, die jeweils ein bestimmtes Buch repräsentieren. Als Wurzelelement oder -knoten dient dabei buecher. Das Ziel besteht nun darin, auf dieses XML-Dokument möglichst einfach in einem PHP-Skript zuzugreifen. Mit SimpleXML ist nichts leichter als das.

Die Funktion zum Einlesen von XML-Dokumenten ist simplexml_load_file. Diese Funktion liest das als Parameter übergebene XML-Dokument ein und gibt ein Objekt zurück.

object simplexml_load_file(string filename)

Das zurückgegebene Objekt entspricht in seiner Struktur exakt dem XML-Dokument, so dass über die Eigenschaften und Indizes auf jeden beliebigen Wert zugegriffen werden kann.

<?php

  $objBuecher = simplexml_load_file('buecher.xml');
  echo $objBuecher->buch[1]->isbn;
  
?>

Listing 10.14: XML-Dokument einlesen und als Objekt nutzen

Zunächst wird das XML-Dokument eingelesen und als Objekt $objBuecher zur Verfügung gestellt. Alle Elemente im XML-Dokument, die Kindelemente des Elements buecher sind, stehen direkt als Eigenschaft des XML-Objekts zur Verfügung.

Existieren mehrere gleiche Elemente, dann sind diese über einen Index ansprechbar. Die Zählung beginnt dabei, wie bei Arrays üblich, mit 0. Das erste Element hat also den Index 0, das zweite den Index 1 usw.

Im Beispielscript wird das Element isbn des zweiten buch-Elements ausgegeben. Das bedeutet also:

3–89842–427–8

Zu viel versprochen? Leichter als auf diese Art werden Sie ein XML-Dokument nicht einlesen können. Das Objekt kann in dieser Form problemlos in Schleifen wie z. B. foreach oder for verwendet werden.

Auch der Zugriff auf die Attribute eines Elements ist mehr als einfach. Dazu nehmen wir ein leicht verändertes XML-Dokument, bei dem die ISBN nicht als Element, sondern als Attribut des Elements buch notiert wird.

<?xml version="1.0"?>
<buecher>
    <buch isbn="3–89842–313–1">
        <titel>Webseiten programmieren und gestalten</titel>
        <autor>Mark Lubkowitz</autor>
        <auflage>1</auflage>
    </buch>
    <buch isbn="3–89842–427–8">
        <title>Einstieg in MySQL</titel>
        <autor>Mark Lubkowitz</autor>
        <auflage>1</auflage>
    </buch>
    <buch isbn="3–89842–557–6">
        <titel>Webseiten programmieren und gestalten</titel>
        <autor>Mark Lubkowitz</autor>
        <auflage>2</auflage>
    </buch>
</buecher>

Listing 10.15: XML-Dokument mit Attributen

Um nun mit PHP die ISBN ausgeben zu können, müssen Sie folgendermaßen vorgehen:

<?php

  $objBuecher = simplexml_load_file('buecher.xml');
  echo $objBuecher->buch[0]['isbn'];
  
?>

Listing 10.16: Zugriff auf Attribute eines Elements

Die echo-Anweisung gibt das Attribut des ersten buch-Elements (Index 0) aus, und das Ergebnis ist:

3–89842–313–1

Auch der schreibende Zugriff auf XML-Dokumente gestaltet sich genauso einfach wie der lesende – ob es nun darum geht, neue Elemente oder Attribute hinzuzufügen oder diese zu ändern.

# Sonstiges

Es gibt noch viele weitere Änderungen, die Einzug in die Version 5 von PHP gehalten haben. Unter anderem steht ein neues relationales DBMS zur Verfügung, das direkt in PHP integriert wurde: SQLite. Auch in Bezug auf die GD-Library hat sich einiges getan, denn nun lassen sich Filter auf Grafiken anwenden. Aus diesem Grunde kann ich Ihnen nur das Buch »PHP 5 – Die Neuerungen« (ISBN: 3–89842–490–1) von Martin Goldmann und Markus Schraudolph ans Herz legen. Es ist bei Galileo Press erschienen und behandelt ausführlich all das, wofür hier leider kein Platz gewesen ist.

# Zusammenfassung

  • Die Webhoster werden wahrscheinlich erst Ende des Jahres auf PHP 5 umstellen.
  • Für den Konstruktor einer Klasse wird ab PHP 5 ein gleich bleibender Name verwendet. Zusätzlich gibt es nun auch einen Destruktor.
  • Eigenschaften und Methoden können nun mit den Schlüsselwörtern public, private und protected geschützt oder frei zugänglich gemacht werden.
  • Ab PHP 5 ist nun auch die Fehlerbehandlung mit try..catch-Anweisungen möglich.
  • Der schreibende und lesende Zugriff auf XML-Dokumente ist dank der SimpleXML-Bibliothek einfacher und effizienter geworden.

# Fragen und Übungen

  1. Welcher Bezeichner wird ab PHP 5 für den Konstruktor einer Klasse verwendet?
  2. Wann wird der Desktruktor einer Klasse ausgeführt?
  3. Mit welcher Funktion können Sie ein XML-Dokument einlesen und als Objekt nutzen?
  4. Können Sie zu einem try-Block auch mehrere catch-Blöcke notieren?
  5. Erstellen Sie einige typisierte Exception-Klassen, z.B. DatabaseException, und nutzen Sie diese in einem Ihrer Scripts.
  6. Kann auf eine Variable, die in einer Klasse als protected deklariert worden ist, in einer von ihr abgeleiteten Klasse zugegriffen werden?