Teil 3: Datenbankabstraktion
- Datenbankabstraktion
- Teil 2: Datenbankabstraktion
- Teil 3: Datenbankabstraktion
Beim Binden geben Sie dann die Nummer des Parameters an, den Sie gerade binden:...
Beim Binden geben Sie dann die Nummer des Parameters an, den Sie gerade binden:
$pdostatement->bindParam(1,
$autorenid);
Alternativ können Sie die gewünschten Parameter auch erst im execute()-Kommando als Array übergeben. Bei einigen Datenbanksystemen unterstützen die PDO auch Ausgabeparameter.
Wenn Sie Paramter ohne Prepared Statements übergeben, sollten Sie diese filtern. Als einheitliche Waffe gegen SQL Injection bietet die Klasse die Methode quote().
$connect->quote($_GET
['parameter']);
Ausgabe
Aber nicht nur beim Ausführen von Anfragen und Übergeben von Werten gibt es verschiedene Ansätze. Auch das Auslesen kann auf verschiedene Arten erfolgen. Mit fetchAll() erhalten Sie einen vollständigen Array.

Dieser enthält einen Array mit allen Datenreihen und erlaubt damit vollständigen Zugriff - natürlich mit dem Nachteil, dass alle Daten im Hauptspeicher landen. Die Datenreihe ist jeweils ein Array mit einem assoziativen Index, der den Feldnamen als Schlüssel besitzt und den Feldinhalt als Wert. Außerdem sind die Werte separat noch als numerischer Index abgelegt:
$object = $pdostatement->fetchAll();
foreach ($object as $value) {
foreach($value as $row_key =>
$row_value) { echo $row_key . ': ' . $row_value . '<br />'; } }
Eine Alternative ist noch fetchObject(). Diese Methode ruft eine Datenreihe als Objekt auf und arbeitet ansonsten wie fetch(). fetchColumn(Nummer) holt sich ein bestimmtes Feld aus der nächsten Reihe. Als Parameter wird eine Spaltennummer übergeben.
LOBs
Große Objekte nehmen in Datenbanken eine Sonderrolle ein. Sie werden oft als BLOB (Binary Large Object) gespeichert. Die PDO bietet für LOBs extra einen Datentyp. Sie können nun zum Beispiel einen Ausgabeparameter verwenden, um ein Bild aus der Datenbank auszulesen.
Hierzu steuern Sie die Ausgabe mit bindColumn(). Dort geben Sie den Parameter für den LOB an. Er erhält als Erstes die Nummer. Da wir hier nur ein Feld abfragen, ist das die 1. Dann folgt eine Variable, die den (B)LOB aufnimmt. Anschließend der Datentyp als Konstante der PDO. Anschließend lesen Sie mit fetch() den ersten Datensatz und speichern dann das Bild mit file_put_contents().
$pdostatement = $connect->
prepare('SELECT bild FROM artikelWHERE autoren_id = ?');
$pdostatement->bindParam(1,
$autorenid);
$pdostatement->execute();
$pdostatement->bindColumn(1, $lob,
PDO::PARAM_LOB);
$pdostatement->fetch();
file_put_contents('bild.png', $lob);
echo '<img src="bild.png" />';
Das Beispiel ist natürlich ein wenig vereinfacht. Um mehrere LOBs auszulesen, verarbeiten Sie diese mit fetch() in einer Schleife. Und beim Speichern der Bilder sollten Sie natürlich testen, ob das Bild mit dem jeweiligen Namen schon existiert. Vielleicht lässt sich der Name ja beispielsweise aus der ID des Artikels oder aus seiner Überschrift generieren.
Bei LOBs gilt es in den PDO zwei Dinge zu beachten: Oracle erwartet eine leicht andere Syntax als andere Datenbanken. Und beim Zeichensatz kann es problematisch werden, wenn die Daten beispielsweise UTF-8-kodiert werden.
Transaktionen
Eine wichtige Datenbankfunktion sind Transaktionen. Dabei werden mehrere Abfragen in einer Transaktion zusammengefasst. Der Vorteil ist, dass die gesamte Transaktion am Ende entweder mit COMMIT bestätigt oder mit ROLLBACK rückumgewandelt werden kann. Diese SQL-Befehle sind allerdings nicht in jeder Datenbank gleich, was Syntax und Verhalten angeht. Deswegen kapseln die PDO das in eigenen Methoden. beginTransaction() steht dabei für den Anfang einer Transaktion, commit() bestätigt die gesamte Transaktion und rollBack() macht sie im Fehlerfall vollständig rückgängig:
$connect->beginTransaction();
//Anweisungen
if (allesok) {$connect->commit();
} else {$connect->rollBack(); }
Leider gibt es bei MySQL hier eine Einschränkung: Bei bestimmten SQL-Statements wie CREATE TABLE und DROP TABLE führt MySQL automatisch ein COMMIT durch. Das heißt, das Rückgängigmachen funktioniert ab diesem Punkt nicht mehr. Sie sehen, komplett lassen sich Datenbankunterschiede nicht beseitigen.
Alternativen
Einige Alternativen zu den PDO finden Sie auf der offiziellen PEAR-Website. Das sehr populäre DB-Paket ist mittlerweile mit der MDB verschmolzen in der MDB2 aufgegangen. Die ursprünglichen Pakete gibt es allerdings nach wie vor.
Die MDB2 ist selbst in PHP geschrieben. Sie setzt wie die PDO auf datenbankspezifische Treiber. Eine der großen Stärken ist die einfache Iterierbarkeit von Ergebnissen. Die MDB2_Iterator erlaubt das Abarbeiten einer vollständigen Rückgabe mehrerer Datenreihen direkt in einer einfachen Schleife, während man in den PDO ein komplettes Ergebnis mit fetchAll erst durchgehen muss.
Dem setzen die PDO das Binden von Parametern entgegen - zwei durchaus unterschiedliche Ansätze. Beim zeilenweisen Auslesen gibt es dagegen keine konzeptionellen Unterschiede. Das heißt, am Ende muss jeder selbst entscheiden, welchem Verfahren er den Vorzug gibt. Für die PDO sprechen hier nicht nur die direkte Integration in PHP, sondern auch die durch C als Basis höhere Performance.