PDO (PHP Data Objects)
- Verbindung herstellen
- Prepared Statements
- mit und ohne Parameter, Varianten der Parameterbindung
- Verweise
Dieser Überblick beschäftigt sich mit konkreten Anwendungsbeispielen von PDO bzw. Prepared Statements mittels PDO. Weitere grundsätzliche Informationen dazu sind in der PHP-Doku zu finden:
Verbindung herstellen
Nachfolgend wird die Verbindung zum DBMS hergestellt.
$dsn = 'mysql:dbname=test;host=localhost;charset=utf8';
$user = 'root';
$pass = '';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
PDO::ATTR_EMULATE_PREPARES => false
];
$pdo = new PDO($dsn, $user, $pass, $options);
Hinweise zu den Optionsparametern
Je nach Vorlieben bzw. Entwicklungsstil können Parameter auch anderweitig gesetzt werden. Nachfolgend zwei übliche Beispiele - weitere Parameter sind in der Doku zu finden.
-
PDO::FETCH_ASSOC
stattPDO::FETCH_OBJ
Fetch-Varianten: http://php.net/manual/de/pdostatement.fetch.php
Hier verwenden wir durchgängig die objektorientierte (OO) Variante für den Zugriff auf die Eigenschaften. -
PDO::ERRMODE_WARNING
stattPDO::ERRMODE_EXCEPTION
Mögliche Error-Modi: http://php.net/manual/de/pdo.error-handling.php
Wiederverwendung der Verbindung
Benötigt eine Funktion oder ein Objekt eine DB-Verbindung, so wird die bestehende PDO-Instanz $pdo
als Parameter übergeben. Dieses Prinzip nennt sich Dependency Injection. In den folgenden Beispielen wird weiters typehinting verwendet.
Beispiel für eine Funktion
function getUsernameById($userID, PDO $pdo) {
// ...
}
// Funktionsaufruf
$username = getUsernameById(23, $pdo);
Beispiel für eine Klasse
class User
{
private $pdo; // Eigenschaft deklarieren
public function __construct(PDO $pdo) {
// PDO-Objekt an die Eigenschaft übergeben
// diese steht nun in der ganzen Klasse
// per $this->pdo zur Verfügung.
$this->pdo = $pdo;
}
// ...
}
// Aufruf / Instantiierung
$user = new User($pdo);
Prepared Statements
Die Parameter für Prepared Statements müssen nicht maskiert werden. Der Treiber übernimmt das automatisch. Wenn eine Anwendung ausschließlich Prepared Statements benutzt, kann sich der Entwickler sicher sein, dass keine SQL-Injection auftreten wird. (Wenn aber trotzdem andere Teile der Abfrage aus nicht zuverlässigen Eingaben generiert werden, ist dies immer noch möglich.)
Einer der Vorteile von PDO ist die Portabilität zwischen den unterschiedlichen DBMS. Um dem zu entsprechen, sollten in der Query keine (MySQL spezifischen) `Backticks` verwendet werden. Daraus resultiert, das auf die Benennung der Spalten entsprechend zu achten ist, um nicht mit den reservierten Keywords des jeweilig verwendeten DBMS zu kollidieren.
Query ohne Parameter
$sql = "SELECT username FROM user";
$stmt = $pdo->prepare($sql);
// Namen einzeln ausgeben
if ($stmt->execute()) {
while ($row = $stmt->fetch()) {
echo $row->username."<br>\n";
}
}
// ODER
// alle Daten in ein Array überführen
$stmt->execute();
$arr = $stmt->fetchAll();
print_r($arr);
Mit Parameter - Bindung der Parameter
Nachfolgende Möglichkeiten bestehen u.a., um die Parameter an das Statement zu binden.
Parameter einzeln binden
// Query vorbereiten
$sql = "SELECT username, gender FROM user WHERE username = :username AND gender = :gender";
$stmt = $pdo->prepare($sql);
// Parameter übergeben und verarbeiten
$username = 'Joachim';
$gender = 'M';
$stmt->bindParam(':username', $username);
$stmt->bindParam(':gender', $gender);
if ($stmt->execute()) {
$row = $stmt->fetch();
echo $row->username;
}
Hinweis
Die Parameterbindung kann alternativ zu bindParam()
mit bindValue()
vorgenommen werden. Die Unterschiede sind in diesem stackoverflow-Beitrag mittels kurzen Beispielen dargestellt.
Parameter per Array binden
// Query vorbereiten
$sql = "SELECT username, gender FROM user WHERE username = :username AND gender = :gender";
$stmt = $pdo->prepare($sql);
// Parameter übergeben und verarbeiten
$username = 'Sarah';
$gender = 'F';
$aParams = array(':username' => $username, ':gender' => $gender);
$stmt->execute($aParams);
echo $stmt->rowCount();
Daten aus Array in DB schreiben
Um Daten mittels Prepared Statements aus einem Array in die DB zu schreiben, kann man folgenden Ansatz nutzen. Verwendet wird dazu wieder das oben erstellte PDO-Objekt $pdo
mit der DB-Verbindung. Das Beispiel entstammt diesen PHP.de-Thread.
// Temporäre Tabelle zum Testen des Scripts
$pdo->query("
CREATE TEMPORARY TABLE temp (
id INT NOT NULL AUTO_INCREMENT,
vorname VARCHAR(255) NOT NULL,
nachname VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
)
");
// unser Daten-Array
$aData = [
['vorname' => 'Hans', 'nachname' => 'Maier'],
['vorname' => 'Peter', 'nachname' => 'Müller'],
['vorname' => 'Robert', 'nachname' => 'Kinz']
];
// in DB schreiben
$sql = "
INSERT INTO temp (" . implode(", ", array_keys($aData[0])) . ")
VALUES (" . implode(", ", array_fill(0, count($aData[0]), "?")) . ")
";
$stmt = $pdo->prepare($sql);
foreach ($aData as $row) {
$stmt->execute(array_values($row));
}
// Test - Daten wieder ausgeben
$result = $pdo->query("SELECT id, vorname, nachname FROM temp");
print_r( $result->fetchAll(PDO::FETCH_ASSOC) );
/*
Array
(
[0] => Array
(
[id] => 1
[vorname] => Hans
[nachname] => Maier
)
[1] => Array
(
[id] => 2
[vorname] => Peter
[nachname] => Müller
)
[2] => Array
(
[id] => 3
[vorname] => Robert
[nachname] => Kinz
)
)
*/
Querverweise
Dieser Beitrag ist fertiggestellt und wurde zuletzt von hausl bearbeitet.
An diesem Beitrag waren bisher beteiligt: hausl