PHP PDO Tutorial: Sichere Datenbank-Zugriffe
PDO (PHP Data Objects) ist die moderne, sichere Methode für Datenbank-Zugriffe in PHP. PDO bietet Prepared Statements, die SQL-Injection verhindern, und unterstützt verschiedene Datenbanken (MySQL, PostgreSQL, SQLite, etc.). Dieses Tutorial führt Sie Schritt für Schritt durch die Verwendung von PDO für sichere, effiziente Datenbank-Operationen.
PDO ist besser als die veralteten MySQL-Funktionen (mysql_*, mysqli_*), weil es Prepared Statements unterstützt, verschiedene Datenbanken abstrahiert, und modernere PHP-Features nutzt. PDO ist der Standard für neue PHP-Projekte.
Schritt 1: Datenbankverbindung herstellen
Erstellen Sie eine PDO-Verbindung mit einem DSN (Data Source Name).
php
<?php
// MySQL Verbindung
$dsn = 'mysql:host=localhost;dbname=meine_datenbank;charset=utf8mb4';
$username = 'benutzer';
$password = 'passwort';
try {
$pdo = new PDO($dsn, $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch (PDOException $e) {
die('Verbindungsfehler: ' . $e->getMessage());
}
?>
Wichtige Attribute: - PDO::ATTR_ERRMODE: Wie Fehler behandelt werden (EXCEPTION ist empfohlen) - PDO::ATTR_DEFAULT_FETCH_MODE: Standard-Fetch-Modus (ASSOC für assoziative Arrays)
SQLite Verbindung:
php
$dsn = 'sqlite:/path/to/database.db';
$pdo = new PDO($dsn);
Schritt 2: Prepared Statements verwenden
Prepared Statements sind essentiell für Sicherheit. Sie verhindern SQL-Injection, indem sie Parameter trennen.
Einfache Query:
php
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
Named Parameters:
php
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email AND status = :status");
$stmt->execute([
'email' => $email,
'status' => 'active'
]);
$user = $stmt->fetch();
Wichtig: Verwenden Sie IMMER Prepared Statements für User-Input. Niemals User-Input direkt in SQL einfügen!
Schritt 3: Daten abfragen (SELECT)
Einzelne Zeile:
php
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
if ($user) {
echo $user['name'];
}
Mehrere Zeilen:
php
$stmt = $pdo->prepare("SELECT * FROM users WHERE status = ?");
$stmt->execute(['active']);
$users = $stmt->fetchAll();
foreach ($users as $user) {
echo $user['name'] . '<br>';
}
Fetch-Modi:
php
// Assoziatives Array (Standard)
$user = $stmt->fetch(PDO::FETCH_ASSOC);
// Numerisches Array
$user = $stmt->fetch(PDO::FETCH_NUM);
// Beides
$user = $stmt->fetch(PDO::FETCH_BOTH);
// Als Objekt
$user = $stmt->fetch(PDO::FETCH_OBJ);
// Als spezifische Klasse
$user = $stmt->fetch(PDO::FETCH_CLASS, 'User');
Schritt 4: Daten einfügen (INSERT)
Einfaches INSERT:
php
$stmt = $pdo->prepare("INSERT INTO users (name, email, password) VALUES (?, ?, ?)");
$stmt->execute([
$name,
$email,
$hashed_password
]);
$new_user_id = $pdo->lastInsertId();
Mehrere Zeilen einfügen:
php
$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
foreach ($users_data as $user_data) {
$stmt->execute([
$user_data['name'],
$user_data['email']
]);
}
Schritt 5: Daten aktualisieren (UPDATE)
php
$stmt = $pdo->prepare("UPDATE users SET name = ?, email = ? WHERE id = ?");
$stmt->execute([
$new_name,
$new_email,
$user_id
]);
$affected_rows = $stmt->rowCount();
Schritt 6: Daten löschen (DELETE)
php
$stmt = $pdo->prepare("DELETE FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$deleted_rows = $stmt->rowCount();
Schritt 7: Transactions verwenden
Transactions ermöglichen es, mehrere Operationen atomar auszuführen - entweder alle erfolgreich oder alle fehlgeschlagen.
php
try {
$pdo->beginTransaction();
// Mehrere Operationen
$stmt1 = $pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
$stmt1->execute([$amount, $from_account]);
$stmt2 = $pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
$stmt2->execute([$amount, $to_account]);
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
echo "Fehler: " . $e->getMessage();
}
Schritt 8: Error-Handling
Exception-Modus (Empfohlen):
php
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$user = $stmt->fetch();
} catch (PDOException $e) {
// Log Error, zeige User-freundliche Nachricht
error_log($e->getMessage());
echo "Ein Fehler ist aufgetreten.";
}
Best Practices
Verwenden Sie Prepared Statements immer: Niemals User-Input direkt in SQL. Prepared Statements sind sicherer und oft schneller (wegen Caching).
Verwenden Sie Exceptions: Exception-Modus macht Error-Handling einfacher und sicherer.
Schließen Sie Verbindungen: PDO schließt Verbindungen automatisch, aber Sie können explizit schließen:
php
$pdo = null;
Validieren Sie Input: Prepared Statements verhindern SQL-Injection, aber validieren Sie Input trotzdem für Datenqualität.
Verwenden Sie Transactions: Für mehrere zusammenhängende Operationen verwenden Sie Transactions.
Häufige Fehler
SQL-Injection durch fehlende Prepared Statements:
php
// FALSCH - NIEMALS SO!
$query = "SELECT * FROM users WHERE id = " . $_GET['id'];
Richtige Lösung:
php
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_GET['id']]);
Fehlende Error-Handling: Immer try-catch für Datenbank-Operationen verwenden.
Vergessen von Transactions: Für mehrere Operationen sollten Transactions verwendet werden.
Kommentare