PHP PDO (PHP Data Objects)


Datenbankschnittstellen in PHP


PDO

DSN (Data Source Name)

// MySQL
$dsn = 'mysql:host=localhost;dbname=datenbank;charset=utf8mb4';

// SQLite
$dsn = 'sqlite:datenbank.db';

// PostgreSQL
$dsn = 'pgsql:host=localhost;port=5432;dbname=datenbank';


Verbindung

Verbindung herstellen ... mit Optionen direkt im Konstruktor

$pdo = new PDO($dsn, 'username', 'passwort', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,        // Exceptions bei Fehlern
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,   // Standard: assoziatives Array
    PDO::ATTR_EMULATE_PREPARES => false                 // echte Prepared Statements
]);

... oder nachträglich setAttribute

$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


einfache Query

nur wenn keine Parameter benötigt werden

$pdo->query("SELECT * FROM users WHERE id = 123");


Achtung !!!

$pdo->query("SELECT * FROM users WHERE name = '$name'");


Warum ist das gefährlich?

Benutzereingaben werden direkt in den SQL-String eingebaut

Angreifer können SQL-Befehle injizieren ... SQL-Injections!

'; DROP TABLE users;--


Prepared Statements

Parameter placeholder ?

$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute(['email@example.com']);
$user = $stmt->fetch();

benannte Parameter :name

$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id AND status = :status");
$stmt->execute([':id' => 1, ':status' => 'aktiv']);


Prepared Statements ?


Binding (manuell)

Parameter in execute Funktion unterstützt keine Parameterüberprüfung 🡲 bindParam(param, var, data_type)

$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->bindValue(1, 'Max', PDO::PARAM_STR);
$stmt->bindValue(2, 'max@test.de', PDO::PARAM_STR);
$stmt->execute();

// oder direkt beim Execute
$stmt->execute(['Max', 'max@test.de']);
Konstante Typ
PDO::PARAM_BOOL Boolean
PDO::PARAM_INT Integer
PDO::PARAM_STR String
PDO::PARAM_LOB Large Object (Bild, Audio, ...)
PDO::PARAM_NULL NULL


Fetch-Möglichkeiten

// assoziatives Array
$row = $stmt->fetch(PDO::FETCH_ASSOC);

// numerisches Array
$row = $stmt->fetch(PDO::FETCH_NUM);

// beides kombiniert (assoziativ + numerisch)
$row = $stmt->fetch(PDO::FETCH_BOTH);

// als Objekt (stdClass)
$row = $stmt->fetch(PDO::FETCH_OBJ);

// eigene Klasse instanziieren
$row = $stmt->fetch(PDO::FETCH_CLASS, 'User');

// Schluessel-Wert-Paare (erste Spalte = Key, zweite = Value)
$options = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);


Schleifen für Fetch

$stmt = $pdo->query("SELECT id, name, email FROM users");

// foreach direkt auf Statement - empfohlen
foreach ($stmt as $row) {
    echo $row['name'];
}

// while + fetch() – klassisch
while ($row = $stmt->fetch()) {
    echo $row['name'];
}

// ... fetch-Status ueberpruefen
while (($row = $stmt->fetch()) !== false) {
    // ...
}

// fetchAll() – alle auf einmal (bei kleinen Ergebnissen)
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) { 
    // ...
}


sonstige Zusätze

// Transaktionen
$pdo->beginTransaction();
$pdo->exec("INSERT INTO ... ");
$pdo->commit();
// bei Fehler: $pdo->rollBack();

// letzte eingefuegte ID
$lastId = $pdo->lastInsertId();

// betroffene Zeilen (UPDATE/DELETE)
$count = $stmt->rowCount();

// Fehlerbehandlung – Exception-Modus
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Fehler-Info auslesen
$error = $stmt->errorInfo();

// Attribut setzen / nachfragen
$pdo->getAttribute(PDO::ATTR_DRIVER_NAME); // z.B. 'mysql'

// SQLSTATE-Code
$sqlstate = $stmt->errorCode();


Fehlerbehandlung

try {
    $pdo = new PDO($dsn, $user, $pass);
} catch (PDOException $e) {
    die("Connection failed: " . $e->getMessage());
}