PHP PDO – Datenbanken

6 Kernkonzepte
Die wichtigsten PDO-Konzepte für die Datenbankarbeit in PHP: PDO · Prepared Statements · fetch() · CRUD · Transactions · Fehlerbehandlung PDO (PHP Data Objects) bietet eine sichere und einheitliche Schnittstelle für den Zugriff auf verschiedene Datenbanken. Diese Konzepte sind essenziell für die Entwicklung robuster und sicherer Webanwendungen.

Verbindung – Datenbank verbinden

new PDO · DSN · charset
// MySQL-Verbindung $dsn = "mysql:host=localhost;dbname=test;charset=utf8mb4"; $pdo = new PDO($dsn, "user", "pass"); // PostgreSQL $dsn = "pgsql:host=localhost;dbname=test;charset=utf8"; // SQLite $dsn = "sqlite:/path/to/database.db";

PDO (PHP Data Objects) ist eine Datenbank-Abstraktionsschicht. Die Verbindung wird über einen DSN (Data Source Name) mit Benutzername und Passwort hergestellt.

Wichtige PDO-Attribute

Attribut Beschreibung
PDO::ATTR_ERRMODE Fehlermodus (z.B. PDO::ERRMODE_EXCEPTION)
PDO::ATTR_DEFAULT_FETCH_MODE Standard-Abrufmodus (z.B. PDO::FETCH_ASSOC)
PDO::ATTR_EMULATE_PREPARES Emulation von Prepared Statements (false für echte)
PDO::MYSQL_ATTR_INIT_COMMAND Befehl nach Verbindung (z.B. "SET NAMES utf8")
Beispiele
// Verbindung mit Fehlerbehandlung
try {
$dsn = "mysql:host=localhost;dbname=test;charset=utf8mb4";
$pdo = new PDO($dsn, "root", "secret");
// Fehlermodus auf Exception setzen
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Standard-Abrufmodus
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// Keine emulierten Prepared Statements
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e) {
echo "Verbindung fehlgeschlagen: " . $e->getMessage();
}
Tipp: Verwenden Sie immer den Exception-Modus (PDO::ERRMODE_EXCEPTION) für eine konsistente Fehlerbehandlung. Die Angabe von charset=utf8mb4 ist wichtig für die korrekte UTF-8-Unterstützung.

Prepared Statements – Sichere SQL-Abfragen

prepare · execute · bindParam · bindValue
// SQL mit Platzhaltern (named placeholders) $stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id"); $stmt->execute([':id' => $id]); // Mit Fragezeichen-Platzhaltern $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$id]);

Prepared Statements schützen vor SQL-Injection, indem sie SQL-Code von Daten trennen. Sie werden mit prepare() vorbereitet und mit execute() ausgeführt.

Beispiele
// Named Placeholders
$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
$stmt->execute([':name' => "Anna", ':email' => "anna@example.com"]);
// bindParam (per Referenz)
$stmt = $pdo->prepare("UPDATE users SET name = :name WHERE id = :id");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$name = "Ben";
$id = 1;
$stmt->execute();
// bindValue (per Wert)
$stmt = $pdo->prepare("SELECT * FROM users WHERE age > ?");
$stmt->bindValue(1, 18, PDO::PARAM_INT);
$stmt->execute();
// LIKE mit Wildcards (Platzhalter escapen)
$search = "%anna%";
$stmt = $pdo->prepare("SELECT * FROM users WHERE name LIKE :search");
$stmt->execute([':search' => $search]);
Tipp: Verwenden Sie immer Prepared Statements, wenn Sie Benutzereingaben in SQL-Abfragen einbinden. Das ist der wichtigste Schutz vor SQL-Injection.

fetch-Modi – Daten abrufen

fetch() · fetchAll() · FETCH_ASSOC · FETCH_OBJ
// Einzelnen Datensatz abrufen $row = $stmt->fetch(PDO::FETCH_ASSOC); // Alle Datensätze abrufen $rows = $stmt->fetchAll(PDO::FETCH_OBJ); // Spaltenwert abrufen $count = $stmt->fetchColumn();

fetch-Modi bestimmen, wie Daten von der Datenbank abgerufen werden. Die wichtigsten Modi sind FETCH_ASSOC (assoziatives Array), FETCH_OBJ (Objekt) und FETCH_BOTH (beides).

Die wichtigsten fetch-Modi

Modus Beschreibung
PDO::FETCH_ASSOC Assoziatives Array (Spaltenname → Wert)
PDO::FETCH_OBJ Objekt (Eigenschaften = Spaltennamen)
PDO::FETCH_BOTH Beides (Standard)
PDO::FETCH_NUM Numerisches Array (Index → Wert)
PDO::FETCH_CLASS Objekt einer bestimmten Klasse
PDO::FETCH_COLUMN Nur eine Spalte (0-basiert)
Beispiele
// FETCH_ASSOC (assoziatives Array)
$stmt = $pdo->query("SELECT id, name FROM users");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['name'];
}
// FETCH_OBJ (als Objekt)
while ($row = $stmt->fetch(PDO::FETCH_OBJ)) {
echo $row->name;
}
// fetchAll (alle Datensätze auf einmal)
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($users as $user) {
echo $user['name'];
}
// fetchColumn (nur eine Spalte)
$stmt = $pdo->query("SELECT COUNT(*) FROM users");
$count = $stmt->fetchColumn();
// FETCH_CLASS (in ein Objekt einer Klasse)
$users = $stmt->fetchAll(PDO::FETCH_CLASS, "User");
Tipp: Setzen Sie den Standard-Abrufmodus mit $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC), um bei jedem fetch den Modus nicht neu angeben zu müssen.

CRUD – Create, Read, Update, Delete

INSERT · SELECT · UPDATE · DELETE
// INSERT $stmt = $pdo->prepare("INSERT INTO users (name) VALUES (:name)"); $stmt->execute([':name' => $name]); // Letzte eingefügte ID $id = $pdo->lastInsertId();

CRUD sind die grundlegenden Datenbankoperationen: Create (INSERT), Read (SELECT), Update (UPDATE), Delete (DELETE).

Beispiele
// CREATE (INSERT)
$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
$stmt->execute([':name' => "Anna", ':email' => "anna@example.com"]);
$id = $pdo->lastInsertId(); // 5
// READ (SELECT)
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute([':id' => $id]);
$user = $stmt->fetch();
// UPDATE
$stmt = $pdo->prepare("UPDATE users SET name = :name WHERE id = :id");
$stmt->execute([':name' => "Anna Müller", ':id' => $id]);
$affected = $stmt->rowCount(); // 1
// DELETE
$stmt = $pdo->prepare("DELETE FROM users WHERE id = :id");
$stmt->execute([':id' => $id]);
$deleted = $stmt->rowCount();
Tipp: rowCount() gibt die Anzahl der betroffenen Zeilen zurück – nützlich, um zu prüfen, ob eine Operation erfolgreich war.

Transaktionen – Atomare Operationen

beginTransaction · commit · rollBack
// Transaktion starten $pdo->beginTransaction(); // Änderungen durchführen $pdo->exec("INSERT INTO ..."); // Erfolgreich abschließen $pdo->commit(); // Bei Fehler rückgängig machen $pdo->rollBack();

Transaktionen ermöglichen es, mehrere Datenbankoperationen als eine Einheit auszuführen. Bei einem Fehler können alle Änderungen mit rollBack() rückgängig gemacht werden.

Beispiele
try {
// Transaktion starten
$pdo->beginTransaction();
// Geld von Konto A abheben
$stmt = $pdo->prepare("UPDATE accounts SET balance = balance - :amount WHERE id = :id");
$stmt->execute([':amount' => $amount, ':id' => $fromId]);
// Geld auf Konto B einzahlen
$stmt = $pdo->prepare("UPDATE accounts SET balance = balance + :amount WHERE id = :id");
$stmt->execute([':amount' => $amount, ':id' => $toId]);
// Transaktion erfolgreich abschließen
$pdo->commit();
} catch (Exception $e) {
// Fehler: Transaktion rückgängig machen
$pdo->rollBack();
echo "Transaktion fehlgeschlagen: " . $e->getMessage();
}
Tipp: Transaktionen sind entscheidend für die Datenkonsistenz bei Operationen, die mehrere Tabellen betreffen. Verwenden Sie sie für Überweisungen, Bestellungen oder andere zusammenhängende Änderungen.

Fehlerbehandlung – Exceptions & Fehlercodes

try · catch · errorInfo · errorCode
// Exception abfangen try { // Datenbankoperation } catch (PDOException $e) { echo "Fehler: " . $e->getMessage(); }

Fehlerbehandlung ist entscheidend für robuste Datenbankanwendungen. Im Exception-Modus werfen PDO-Methoden PDOException bei Fehlern. Alternativ können Fehlercodes mit errorCode() abgefragt werden.

Beispiele
// Exception-Handling (empfohlen)
try {
$stmt = $pdo->prepare("INSERT INTO users (name) VALUES (:name)");
$stmt->execute([':name' => $name]);
} catch (PDOException $e) {
// Fehlerinformationen ausgeben
echo "SQL-Fehler: " . $e->getMessage();
echo "Code: " . $e->getCode();
}
// Fehlercodes abfragen (ohne Exception)
$stmt = $pdo->prepare("INVALID SQL");
if ($stmt->execute() === false) {
echo "Fehlercode: " . $stmt->errorCode();
print_r($stmt->errorInfo());
}
// Spezifische Exception-Typen abfangen
catch (PDOException $e) {
if ($e->getCode() == 23000) { // Integrity constraint violation
echo "Duplikat oder Fremdschlüsselverletzung";
}
}
Tipp: Im Entwicklungsmodus sollten Sie Exceptions mit var_dump($e) detailliert ausgeben. Im Produktionsmodus loggen Sie die Fehler und zeigen dem Benutzer eine allgemeine Fehlermeldung.

PDO im Überblick

DSN Data Source Name
mysql:host=...;dbname=...
prepare() Statement vorbereiten
Schützt vor SQL-Injection
execute() Statement ausführen
Mit Parametern
fetch() Daten abrufen
FETCH_ASSOC, FETCH_OBJ
Transaction Transaktionen
begin, commit, rollBack
Exception Fehlerbehandlung
PDOException

Quick Summary

new PDO
Verbindung
prepare
Prepared Statement
fetch
Daten abrufen
INSERT
CRUD
commit
Transaktionen
catch
Fehlerbehandlung
$pdo = new PDO($dsn, $user, $pass); · $stmt = $pdo->prepare("SELECT ... WHERE id = :id"); · $stmt->execute([':id' => $id]);