← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

PDO

php PHP 5.1+ Intermediate

Also Known As

PHP PDO PHP Data Objects PDO extension

TL;DR

PHP Data Objects — a database abstraction layer supporting prepared statements across multiple database drivers.

Explanation

PDO provides a consistent interface to multiple database backends (MySQL, PostgreSQL, SQLite, etc.) through a unified API. It supports both named (:name) and positional (?) parameter placeholders in prepared statements. PDO::ATTR_EMULATE_PREPARES should be set to false to ensure the database — not PHP — handles the parameterisation. PDO throws PDOException on failure when PDO::ATTR_ERRMODE is set to PDO::ERRMODE_EXCEPTION.

Diagram

flowchart LR
    APP2[PHP App] --> PDO2[PDO layer<br/>database agnostic]
    PDO2 -->|DSN string| MYSQL2[(MySQL)]
    PDO2 -->|DSN string| PGSQL[(PostgreSQL)]
    PDO2 -->|DSN string| SQLITE[(SQLite)]
    subgraph Safe_Query_Flow
        PREP[prepare SQL with placeholders]
        BIND2[execute with values array]
        FETCH[fetch results as array object]
        PREP --> BIND2 --> FETCH
    end
    subgraph Prevents
        INJ[SQL injection<br/>params never interpreted as SQL]
    end
style PDO2 fill:#1f6feb,color:#fff
style PREP fill:#238636,color:#fff
style INJ fill:#238636,color:#fff

Common Misconception

Using PDO automatically prevents SQL injection. PDO with prepared statements prevents SQLi, but PDO also supports emulated prepared statements (PDO::ATTR_EMULATE_PREPARES) which do client-side interpolation — always disable emulation and use native prepared statements.

Why It Matters

PDO is the standard PHP database abstraction layer — it provides prepared statements, consistent error handling, and supports multiple databases with the same API. Using mysql_* functions or raw string concatenation instead is a security and maintainability failure.

Common Mistakes

  • Using PDO::ERRMODE_SILENT (the default) — errors fail silently and are nearly impossible to debug.
  • Leaving PDO::ATTR_EMULATE_PREPARES enabled — use native prepared statements for proper SQL injection protection.
  • Catching PDOException but swallowing it without logging — you lose all diagnostic information.
  • Creating a new PDO connection on every function call instead of sharing a single connection.

Code Examples

✗ Vulnerable
// Interpolated variables — SQL injection:
$id = $_GET['id'];
$stmt = $pdo->query("SELECT * FROM users WHERE id = $id");

// Prepared statement with PDO:
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute([':id' => (int)$id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
✓ Fixed
\$pdo = new PDO(
    'mysql:host=localhost;dbname=myapp;charset=utf8mb4',
    \$_ENV['DB_USER'],
    \$_ENV['DB_PASS'],
    [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false, // native prepared statements
    ]
);

// Named placeholders
\$stmt = \$pdo->prepare('SELECT * FROM users WHERE email = :email AND active = :active');
\$stmt->execute([':email' => \$email, ':active' => 1]);
\$user = \$stmt->fetch();

// Insert + last insert ID
\$stmt = \$pdo->prepare('INSERT INTO orders (user_id, total) VALUES (?, ?)');
\$stmt->execute([\$userId, \$total]);
\$orderId = \$pdo->lastInsertId();

// Transactions
\$pdo->beginTransaction();
try { \$pdo->commit(); } catch (\Throwable \$e) { \$pdo->rollBack(); throw \$e; }

Added 15 Mar 2026
Edited 22 Mar 2026
Views 37
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 1 ping T 0 pings W 0 pings T 1 ping F 1 ping S 2 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 3 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Perplexity 11 Amazonbot 7 Ahrefs 5 Unknown AI 3 Google 2 SEMrush 2 ChatGPT 2
crawler 29 crawler_json 2 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Use PDO with ERRMODE_EXCEPTION and EMULATE_PREPARES=false — real prepared statements, not emulated ones, provide true SQL injection protection
📦 Applies To
PHP 5.1+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
PDO::ATTR_EMULATE_PREPARES not set to false; ERRMODE not set to ERRMODE_EXCEPTION; no charset in DSN
Auto-detectable: ✓ Yes phpstan semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Low ✗ Manual fix Fix: Medium Context: File Tests: Update
CWE-89

✓ schema.org compliant