Seitenleiste

Inhalt

PDO - Die unabhängige Datenbankerweiterung

Fast jeder PHP-Programmierer kennt es: Die unübersichtlichen oder 2000 Zeilen große Dateien, und das nur weil man wissen möchte, welche Datenbank Erweiterung das Ziel System nutzt, und diese auch zu nutzen.
Eine Lösung ist schon lange da, aber kaum beachtet: PDO.
PDO steht für PHP Data Objects, also PHP Daten Objekte. Okay, dieser Name ist ziemlich irreführend, da man dabei eher an eine Erweiterung denkt, welche User Daten verarbeitet. Dies ist aber nicht der Fall: Denn diese Klasse, die in jedem PHP System seit PHP 5.1 Standardmäßig aktiviert und installiert ist, macht nichts anderes, als eine unabhängige Datenbankerweiterung darzustellen. PDO unterstützt folgende Datenbanksysteme durch Treiber (Die mit dem jeweiligen Datenbanksystem automatisch mitinstalliert werden)

PDO Treiber

Anmerkung: Das in Klammern angegebene sind die Systeme, nicht die Treiber

  • PDO_CUBRID (Cubrid)
  • PDO_DBLIB (FreeTDS/Microsoft SQL Server / Sybase)
  • PDO_FIREBIRD (Firebird/Interbase 6)
  • PDO_IBM (IBM DB2)
  • PDO_INFORMIX (IBM Informix Dynamic Server)
  • PDO_MYSQL (MySQL 3.x/4.x/5.x und neuer, Momentan)
  • PDO_OCI (Oracle Call Interface)
  • PDO_ODBC (ODBC v3,IBM DB2,unixODBC und win32 ODBC)
  • PDO_PGSQL (PostgreSQL)
  • PDO_SQLITE (SQLite 3 und SQLite 2)
  • PDO_SQLSRV (Microsoft SQL Server / SQL Azure)
  • PDO_4D (4D)

…und genau dadurch zeichnet sich PDO noch aus: Es existiert eine große Auswahl an unterstützten Datenbanksystemen für alle gibt es die gleichen Funktionen. D.h wir müssen nicht mehr zwischen Befehlen jeweiliger Datenbanksysteme wechseln, nein wir können für jede die selbe Syntax verwenden ( Die SQL Syntax ist nicht unabhängig!).

PDO mit dem jeweiligen Datenbanksystem initialisieren

PDO bietet eine sehr komfortable Methode um das gewünschte Datenbanksystem auszuwählen, sie wird direkt in die initialisierende Funktion geschrieben, deren Syntax die folgende ist:

<?php 
$pdoObj = new PDO("Treibername; dbname=Datenbankname;host=Hostadresse", "Username", "Passwort");
 ?>

„Treibername“ repräsentiert eine der oben aufgeführten Konstanten ohne den Abschnitt „PDO_“, d.h dass PDO_MYSQL in der Initialisierung einfach nur „mysql“ geschrieben wird. „dbname=Datenbankname“ bedeutet, dass die Datenbank „Datenbankname“ angewählt wird, mit „dbname=“ wird angegeben, dass die darauffolgenden Datenbank (hier „Datenbankname“) benutzt werden soll. Mit „host=“ wird PDO angewiesen, mit dem Host „Hostname“ zu verbinden, welcher häufig „localhost“ und/oder „127.0.0.1“ lautet.

Datenbank abfragen absetzen und verarbeiten

Abfragen senden zu können, ist das A und O jeder Datenbankerweiterung. Mit PDO ist das genauso wie mit manch anderen Systemen: Man definiert eine Variable, die das Resultat beinhaltet, nimmt das Objekt, das die Verbindung zum Datenbankserver repräsentiert, und über die Resultatsvariable kann die Abfrage weiter verarbeitet werden. Das ganze sieht ungefähr so aus:

<?php
//Initialisiere PDO
$pdoObj = new PDO(//s.o);
//Abfrage absetzen und Ergebnis speichern
$result = $pdoObj->query(„SELECT * FROM tabelle WHERE feldname = Vergleich“);
//Ergebnis zu einem assoziativen Array verarbeiten
$tabelle = $result->fetch(PDO::FETCH_ASSOC);
?>

PDO hat eine eigene Result-Klasse, über die das Resultat verarbeitet wird. Dabei muss darauf geachtet werden, dass das Resultat in einer Variable gespeichert wird. Also:

<?php
$Objekt = //Siehe oben
$ResultObjekt = $Objekt->query(SQL);
$Verarbeitungsobjekt = $ResultObjekt->Verarbeitungsmethode; //Oder auch PDOStatemant als Klasse
?> 

John Doe Fragt: „Okay, ein Query wurde abgesetzt, aber wie verarbeite ich ihn? Ich meine, wie kann ich damit arbeiten?“ Es gibt verschiedene Methoden/Funktionen mit denen man die Abfragen verarbeiten kann, aber die wohl Wichtigste ist „$Verarbeitungsobjekt= $ResultObjekt→fetch(VerarbeitungsStil);“. „VerarbeitungsStil“ beschreibt eine klasseninterne Konstante für die Art und Weise, wie mit dem Objekt umgegangen werden soll. Die folgenden Konstanten sind die wohl wichtigsten (es sollte darauf geachtet werden, dass diese ausgeschrieben werden).

  • PDO::FETCH_ASSOC Gibt ein assoziatives Array zurück, Indizies sind die Bezeichnungen der Tabellen-Spalten (z.b „$Verarbeitungsobjekt['Spalten_Name']“)
  • PDO::FETCH_NUM Gibt ein Array mit einem nummerischen Index zurück, sortiert nach der Reihenfolge der Spalten (z.b „$Verarbeitungsobjekt['0']“).
  • PDO::FETCH_OBJ Erstellt eine Pseudo-Klasse mit den Spaltennamen als Methoden (z.b „$Verarbeitungsobjekt→spaltenname;“ oder „$Verarbeitungsobjekt→id“ - da dieser Name sehr oft verwendet wird).

In den runden Klammern wurden hilfreiche Beispiele angegeben, welche wohl alles erklären sollten ;)

Ein erstes vollwertiges Beispiel

Die SQL Syntax von PDO ist, wie schon erwähnt, diejenige für das gewählte Datenbanksystem. D.h dass wir diese Codes dann leider doch selbst „validieren“ müssen. Das Beispiel besitzt eine Tabelle namens „Kunden“ mit den Feldern „kundenID“, „Vorname“, „Nachname“ und „MailAdresse“. Die genutzte Datenbankerweiterung ist hier MySQL. Die Tabelle:

KundenTabelleCreate.sql
CREATE TABLE `Kunden` (
`kundenID` INT(4) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`Vorname` VARCHAR(20) NOT NULL,
`Nachname` VARCHAR(20) NOT NULL,
`MailAdresse` VARCHAR(40) NOT NULL)

Auch das einfügen der Daten funktioniert wie auch sonst über z.B folgenden SQL-Code:

KundenTabelleInto.sql
INSERT INTO `Kunden` (`kundenID`, `Vorname`, `Nachname`, `MailAdresse`) VALUES (NULL, 'John', 'Doe', 'johndoe@JohnDoeTown.com')

Okay, jetzt schreiben wir nur noch ein kleines Skript welches die Daten ausgibt, und →Tada:

KundenAusgabePDO.php
<?php
//Mit der Datenbank verbinden
$pdoObj = new PDO("mysql:dbname=AwesomeDB;host=localhost", "Awesome", "AwesomePasswort");
//Datensatz Nr.1 auswählen
$ResultObjekt = $pdoObj->query("SELECT * FROM Kunden WHERE kundenID = 1");
//Resultat an $StatementObjekt binden, PDO::FETCH_OBJ gibt ja „Methodisch“ aus
$StatementObjekt = $ResultObjekt->fetch(PDO::FETCH_OBJ);
//Daten anzeigen (ausgeben)
echo "Kunden ID: ".$StatementObjekt->kundenID."<br />
Vorname:".$StatementObjekt->Vorname."<br />
Nachname: ".$StatementObjekt->Nachname."<br  />".
"<a href='mailto:".$StatementObjekt->MailAdresse."' > Mail an ".
$StatementObjekt->Vorname." ".$StatementObjekt->Nachname." Senden</a>";
?>

…Das Ganze ist extra auskommentiert, so dass es gut möglich ist den Code zu verstehen.

Fehler erkennen und ausgeben

Es ist ganz klar, dass man wissen muss ob ein Fehler vorliegt oder nicht. Bei PDO gibt es dafür 2 klasseninterne Funktionen: PDO::errorCode() und PDO::errorInfo(). Das funktioniert auch hier ganz einfach: Ein Query wurde ausgeführt, und anhand der Variable des Resultats kann man auf Fehler prüfen…

//...s.o Verbindung
$ResultsObj = $pdoObj->query("Wrong SQL Code");
//Auf Fehler prüfen
if(!$ResultsObj){//Fehler ausgeben, falls einer existiert
	print_r($pdoObj->errorInfo());
	die();
}
?>

…denn ein PDO-Query gibt bei einem Fehler immer false zurück, und darauf kann geprüft werden. Dann kann man den Fehler über das Initialisierungsobjekt ausgeben lassen…und das entweder mit einer Nummer (PDO::errorCode()) oder eine Beschreibung des Fehlers (PDO::errorInfo()).

Mit freundlichen Grüßen, Leon Giesenkämper