PDO(PHP Data Object) ist der moderne Weg mit PHP5 auf die Datenbank zuzugreifen. Es bietet eine Abstraktionsschicht für den Datenzugriff. Unabhängig vom verwendeten DBMS können die selben Funktionen verwenden.
PDO räumt außerdem mit vielen Sicherheitsängsten auf, die man von anderen Datenbank-Schnittstellen kennt. Die vielen Wege die teilweise zum selben Ergebnis führen schrecken viele Programmierer ab, daher soll dieses Tutorial einen konsistenten Weg liefern.
Konfiguration
Eine gängige Art die Konfigurationvariablen zu hinterlegen ist eine finale Klasse mit Konstanten. Sie benötigt relativ wenig Prozess Overhead.
== Verbindung herstellen ==
Einleitend wurde erläutert, dass PDO eine Abstraktionsschicht für den Datenbankzugriff bereitstellt. Durch Abstraktion folgert Einschränkung - nämlich auf den Nenner des schwächsten unterstützen DBMS. Aus mehreren Gründen macht es Sinn den Datenbankzugriff weiter zu kapseln.
Wir erstellen uns daher eine neue Klasse "MyDB" die als Singleton implementiert wird, somit wird verhindert, dass in der selben PHP Anwendung mehrmals die Verbindung hergestellt wird.
Außerdem erstellen wir eine persistente Verbindung - das bietet sich bei den meisten Webanwendungen an.
Alles anzeigen
== Datenbankänderungen ==
Die einfachste Form von Datenbankzugriffen stellt das Ändern kleiner Daten dar. Parameter die man per Formular übergibt oder über die URL erhält, werden als Array-Parameter durch das execute() Statement gebunden.
Außerdem fällt auf, dass der SQL-String durch das prepare Statement vorbereitet wird. Das ist ein Performance Faktor, sollte man das selbe "Prepared Statement" mehrmals mit unterschiedlichen Parameter ausführen wollen (was ein extrem seltener Fall ist).
== Neue Datenbankeintrage: ID des Datensatzes ==
Werden auto_increment (MySQL) oder SERIAL (postgreSQL) Felder genutzt, kümmert sich das DBMS bei neuen Einträgen um die neuen Primärschlüssel. Sie werden mit der Funktion lastInsertID abgefragt.
== Datenbankabfragen ==
Datenbankabfragen werden genauso wie Änderungen konstruiert - einzig die zusätzliche Methode fetch() wird danach aufgerufen.
Wir haben eingangs beim Konstruieren den Standard Fetch-Modus auf ASSOC geändert. Dadurch erhalten wir ein Array Objekt mit dem Spaltennamen als Schlüssel und dem Inhalt als Wert erhalten. Führen wir die fetch() Funktion mehrmals durch erhalten wir alle Zeilen (falls mehrere vorhanden sind).
Alles anzeigen
== Mehrere Daten abfragen ==
Häufig werden einfach alle Daten abgefragt, die man per SQL String definiert. Statt der Methode fetch() benutzt man dazu die Methode fetchAll(). Die Rückgabe der Funktion ist ein normales zweidimensionales Array, über das man mit foreach iterieren kann.
Alles anzeigen
== Kommaseparierte Liste mit IN ==
MySQL und andere DBMS bieten die Möglichkeit kommaseparierte Listen mit IN zu verarbeiten.
Der SQL String um die Benutzer 1,3 und 5 zu löschen würde folgendermaßen aussehen:
Um eine kommaseparierte Listen verarbeiten zu können kennt das PDO leider keine Möglichkeit.
Die Klasse MyDB wird daher um eine spezielle implode Methode erweitert:
Alles anzeigen
Das Beispiel erweitern wir wie folgt:
Die Methode implode() liefert einen String mit Platzhaltern zurück:
Zusätzlich wird das als Referenz übergebene Array $pdoparams um die Inhalte erweitert. Nach Ausführung von implode sieht das Array also wie folgt aus:
Das execute() bindet diese Parameter an den String und das Statement wird sicher ausgeführt. Die Lösung ist besser als sich den String mit PHP Stringfunktionen selbst zusammen zu bauen, da das PDO nur auf diese Art vor SQL Injections schützt.
== Code Download ==
Den fertigen Code von Klasse und dem letzten Beispiel gibt es zum Download unter demo.easy-coding.de/php/pdo/download.zip.
PDO räumt außerdem mit vielen Sicherheitsängsten auf, die man von anderen Datenbank-Schnittstellen kennt. Die vielen Wege die teilweise zum selben Ergebnis führen schrecken viele Programmierer ab, daher soll dieses Tutorial einen konsistenten Weg liefern.
Konfiguration
Eine gängige Art die Konfigurationvariablen zu hinterlegen ist eine finale Klasse mit Konstanten. Sie benötigt relativ wenig Prozess Overhead.
== Verbindung herstellen ==
Einleitend wurde erläutert, dass PDO eine Abstraktionsschicht für den Datenbankzugriff bereitstellt. Durch Abstraktion folgert Einschränkung - nämlich auf den Nenner des schwächsten unterstützen DBMS. Aus mehreren Gründen macht es Sinn den Datenbankzugriff weiter zu kapseln.
Wir erstellen uns daher eine neue Klasse "MyDB" die als Singleton implementiert wird, somit wird verhindert, dass in der selben PHP Anwendung mehrmals die Verbindung hergestellt wird.
Außerdem erstellen wir eine persistente Verbindung - das bietet sich bei den meisten Webanwendungen an.
Quellcode
- class MyDB {
- private static $db;
- static public function getInstance() {
- if(!self::$db) {
- self::$db = new PDO(
- 'mysql:host='.Configuration::DB_HOST.';dbname='.Configuration::DB_DATABASE.';port='.Configuration::DB_PORT,
- Configuration::DB_USER,
- Configuration::DB_PASSWORD,
- array(
- PDO::ATTR_PERSISTENT => true,
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ,
- PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
- )
- );
- }
- return self::$db;
- }
- }
== Datenbankänderungen ==
Die einfachste Form von Datenbankzugriffen stellt das Ändern kleiner Daten dar. Parameter die man per Formular übergibt oder über die URL erhält, werden als Array-Parameter durch das execute() Statement gebunden.
Außerdem fällt auf, dass der SQL-String durch das prepare Statement vorbereitet wird. Das ist ein Performance Faktor, sollte man das selbe "Prepared Statement" mehrmals mit unterschiedlichen Parameter ausführen wollen (was ein extrem seltener Fall ist).
== Neue Datenbankeintrage: ID des Datensatzes ==
Werden auto_increment (MySQL) oder SERIAL (postgreSQL) Felder genutzt, kümmert sich das DBMS bei neuen Einträgen um die neuen Primärschlüssel. Sie werden mit der Funktion lastInsertID abgefragt.
== Datenbankabfragen ==
Datenbankabfragen werden genauso wie Änderungen konstruiert - einzig die zusätzliche Methode fetch() wird danach aufgerufen.
Wir haben eingangs beim Konstruieren den Standard Fetch-Modus auf ASSOC geändert. Dadurch erhalten wir ein Array Objekt mit dem Spaltennamen als Schlüssel und dem Inhalt als Wert erhalten. Führen wir die fetch() Funktion mehrmals durch erhalten wir alle Zeilen (falls mehrere vorhanden sind).
Quellcode
== Mehrere Daten abfragen ==
Häufig werden einfach alle Daten abgefragt, die man per SQL String definiert. Statt der Methode fetch() benutzt man dazu die Methode fetchAll(). Die Rückgabe der Funktion ist ein normales zweidimensionales Array, über das man mit foreach iterieren kann.
Quellcode
- $pdoparams = array(
- ':username' => "%".$_REQUEST['username']."%",
- ':minage' => $_REQUEST['minage'],
- ':maxage' => $_REQUEST['maxage']
- );
- $sql = "SELECT *
- FROM user
- WHERE username LIKE :username
- AND age BETWEEN :minage AND :maxage";
- $stmt = MyDB::getInstance()->prepare($sql);
- $stmt->execute($pdoparams);
- foreach($stmt->fetchAll() as $row) {
- print_r($row);
- }
== Kommaseparierte Liste mit IN ==
MySQL und andere DBMS bieten die Möglichkeit kommaseparierte Listen mit IN zu verarbeiten.
Der SQL String um die Benutzer 1,3 und 5 zu löschen würde folgendermaßen aussehen:
Um eine kommaseparierte Listen verarbeiten zu können kennt das PDO leider keine Möglichkeit.
Die Klasse MyDB wird daher um eine spezielle implode Methode erweitert:
Quellcode
Das Beispiel erweitern wir wie folgt:
Die Methode implode() liefert einen String mit Platzhaltern zurück:
Zusätzlich wird das als Referenz übergebene Array $pdoparams um die Inhalte erweitert. Nach Ausführung von implode sieht das Array also wie folgt aus:
Das execute() bindet diese Parameter an den String und das Statement wird sicher ausgeführt. Die Lösung ist besser als sich den String mit PHP Stringfunktionen selbst zusammen zu bauen, da das PDO nur auf diese Art vor SQL Injections schützt.
== Code Download ==
Den fertigen Code von Klasse und dem letzten Beispiel gibt es zum Download unter demo.easy-coding.de/php/pdo/download.zip.
22.201 mal gelesen
Torben Brodt -
Bei extrem großen Datensätzen kann die fetchAll Methode Probleme bereiten, da alle Daten in ein einziges Array geladen wird - also gleichzeitig alles im Arbeitsspeicher gehalten wird.
Ruft man fetch() einzeln auf, entspricht dies dem Vorgehen eines Iterators.
Ich bin am überlegen ob man hier mit SPL nicht eine noch einfachere Syntax bauen könnte.
Informationen dazu unter [url]http://www.phpro.org/tutorials/Introduction-to-SPL.html#8[/url]