[PHP & Datenbanken] Ein kurzer Einstieg in PDO und Prepared Statements - Druckversion +- PHP Rocks (https://www.php-rocks.de) +-- Forum: Knowledge Base (https://www.php-rocks.de/https://www.php-rocks.de/forum/18-knowledge-base.html) +--- Forum: Tutorials (https://www.php-rocks.de/https://www.php-rocks.de/forum/20-tutorials.html) +--- Thema: [PHP & Datenbanken] Ein kurzer Einstieg in PDO und Prepared Statements (/https://www.php-rocks.de/thema/49-ein-kurzer-einstieg-in-pdo-und-prepared-statements.html) |
Ein kurzer Einstieg in PDO und Prepared Statements - Arne Drews - 27.04.2015 Was ist PDO? PDO steht für PHP Data Objects und stellt eine Schnittstelle bereit, um mit PHP auf Datenbanken zugreifen zu können. Verwendet wird dafür ein spezifischer Datenbanktreiber, über den die Verbindung zum Datenbankserver hergestellt wird. Durch die PDO-Abstraktionsschicht kann dann, ganz gleich welche Datenbank verwendet wird, mit ein und denselben Methoden Abfrage erstellen, Daten lesen/schreiben etc. PDO bietet die Möglichkeit, Prepared Statements zu verwenden, um die Gefahr von SQL-Injection zu verringern. Wie sieht das in der Praxis aus? PDO bietet zwei wichtige Objekte. Als erstes natürlich das PDO -Objekt selbst, das grob gesagt die Verbindung zur Datenbank repräsentiert.Und als zweites das PDOStatement -Objekt, das die Verwendung von Prepared-Statements erlaubt.Zunächst benötigen wir eine Instanz der Klasse PDO , die wir mit einem einfachen Aufruf des Konstruktors erhalten:PHP-Code: $pdoObject = new PDO( $sDsn, $sUsername, $sPassword, $aOptions ); Schauen wir uns die Parameter zum Verständnis mal genauer an:
$sUserame und $sPassword selbsterklärend sein sollten, spare ich mir die weitere Ausführung dazu und gehe nur auf $sDsn und $aOptions ein.Data Name Source ( DSN ) - $sDsn In der Data Name Source geben wir die notwendigen Parameter für den Verbindungsaufbau an. Als Beispiel soll folgende gültige DSN genügen: PHP-Code: $sDsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
Verbindungsoptionen - $aOptions Über die Verbindungsoptionen können wir der Verbindung Parameter mitgeben, die das Verhalten beeinflussen. Einige Verbindungsoptionen findet ihr u.a. hier: PDO - ATTR_*- Konstanten Für unser Beispiel nutzen wir die folgenden drei Parameter: PHP-Code: $aOptions = array(
Ich möchte im nächsten Step auf PreparedStatement mit PDOStatement eingehen.PreparedStatements Prepared Statements enthalten im Gegensatz zu einer Standard-Anweisung eine vorbereitete, die anstelle der Parameterwerte Platzhalter enthält. Mit diesem Prinzip ist es möglich, daß wir SQL-Injection effektiv verhindern. PDO bietet wie bereits erwähnt das Objekt PDOStatement , welches PreparedStatements unterstützt. Ein Objekt der Klasse PDOStatement muß nicht explizit instanziiert werden, dies geschieht i.d.R. beim Aufruf von PDO::prepare() , das eine Query für die Ausführung vorbereitet und ein Objekt vom Typ PDOStatement zurückgibt.Die Verwendung ist genau so einfach, wie bisher: PHP-Code: $pdoStmnt = $pdoObject->prepare( "SELECT email FROM mytable" ); $pdoStmnt ein Objekt vom Typ PDOStatement . Aber wo liegt darin jetzt der Vorteil? Zumal die Abfrage bisher noch nicht einmal an die Datenbank gesendet wurde.Nun, ein Vorteil liegt darin, daß wir an das Statement Parameter binden können, für die wir zuvor einen Marker oder Platzhalter gesetzt haben. Marker und Platzhalter können entweder als Fragezeichen ( ? ) oder als benannter Platzhalter ( :platzhalter ) gesetzt werden. Das Binden der Parameter-Werte ist über die Methoden PDOStatement::bindParam() und PDOStatement::bindValue() möglich.Beispiel: PHP-Code: $sUserLastName = 'Mustermann'; HinweisBei Verwendung von Fragezeichen als Platzhalter gibt der erste Parameter vonPDOStatement::bindParam() und PDOStatement::bindValue() den Offset, also die Position des zu ersetzenden Parameters in der Query an. Dabei beginnt die Nummerierung bei 1 und nicht, wie bspw. von Arrays gewohnt bei 0. Mit Verwendung der benannten Parameter sind wir unabhängig von der Offset-Angabe und zudem in der Lage in größeren Queries vorkommende Platzhalter-Duplikate mit nur einer Zuweisung über PDOStatement::bindParam() oder PDOStatement::bindValue() zu ersetzen.PHP-Code: $pdoStmnt = $pdoObject->prepare( "SELECT email FROM mytable WHERE firstname=:username OR lastname = :username" ); Wir können als dritten Parameter der Methode PDO::bindParam() und PDO::bindValue() den Datentyp des gebundenen Wertes angeben. Die gebräuchlichsten Konstanten sind in diesem Fall PARAM_INT und PARAM_STR , welches gleichzeitig der Default ist, sofern wir nichts angeben. Weitere Konstanten und Beschreibungen findet ihr hier: PDO - Vordefinierte KonstantenJetzt haben wir zwar etwas über das Objekt PDOStatement und dessen Vorteile gelernt, aber wie bekomme ich nun das Ergebnis meiner Query zur weiteren Verarbietung?Nun, dazu müssen wir die Query zunächst mal an die DB senden. Das machen wir mit der Methode PDOStatement::execute() :PHP-Code: $pdoStmnt->execute(); $pdoStmnt enthält nun nach erfolgreicher Ausführung das Ergebnis der Abfrage. Aber wie kommen wir da jetzt ran?Hierfür stehen uns die Methoden PDOStatement::fetch() und PDOStatement::fetchAll() zur Verfügung.HinweisPDOStatement::fetch() und PDOStatement::fetchAll() geben immer ein assoziatives Array zurück, es sei denn wir geben der gewünschten Datentypen als dritten Parameter an oder ändern diesen explizit über die Optionen des Verbindungsaufbaus bzw. mit der Methode PDO:: setAttribute() unmittelbar nach dem Verbindungsaufbau. Das Attribute heißt ATTR_DEFAULT_FETCH_MODE und die akzeptierten Werte können hier nachgelesen werden: PDOStatement::fetch() . Da wir durchgehend mit Objekten arbeiten wollen, haben wir uns für den Wert PDO::FETCH_OBJ entschieden.Erwartet man mehrere Datensätze und möchte diese gesammelt zurück bekommen, hilft die Methode PDOStatement::fetchAll() , die im Grunde genau wie PDOStatement::fetch() arbeitet, mit dem Unterschied, daß alle vorhandenen Datensätze zurück gegeben werden.HinweisIn der gängigen Praxis kommt es eher seltener vor, daß alle Datensätze zunächst gefetcht und dann verarbeitet werden. In den meisten Fällen wird über einenwhile -Kontext jede Datenzeile des Ergebnisses direkt verarbeitet:PHP-Code: while ( $dsRow = $pdoStmnt->fetch() ) { Das komplette Code-Beispiel PHP-Code: // vorbereitende Variablen für den Verbindungsaufbau |