PHP PDO

PDO class reference: connections, methods, constants, error handling.

Intermediate
Key PointsPDO is a uniform database abstraction — one API, any driver.

Connecting

PHP
<?php
$dsns = [
    "mysql"  => "mysql:host=127.0.0.1;dbname=demo;charset=utf8mb4",
    "pgsql"  => "pgsql:host=127.0.0.1;dbname=demo",
    "sqlite" => "sqlite:/var/data/demo.db",
];

foreach ($dsns as $driver => $dsn) {
    echo $driver . " => " . strtok($dsn, ":") . "\n";
}

echo "可用驱动: " . implode(",", PDO::getAvailableDrivers()), "\n";
Output
mysql => mysql
pgsql => pgsql
sqlite => sqlite
可用驱动: mysql,sqlite

Attribute constants

ConstantEffect
ATTR_ERRMODE错误模式(建议 ERRMODE_EXCEPTION)
ATTR_DEFAULT_FETCH_MODE默认取数模式
ATTR_EMULATE_PREPARES是否模拟预处理(建议 false)
ATTR_STRINGIFY_FETCHES是否把数字转成字符串
ATTR_PERSISTENT持久连接
ATTR_TIMEOUT连接超时秒数
ATTR_CASE列名大小写处理

Core methods

MethodPurpose
prepare预编译语句
execute执行(传参或空数组)
query执行无参 SQL
exec执行并返回影响行数(无结果集)
fetch取一行
fetchAll取全部
fetchColumn取一个值
rowCount影响行数
lastInsertId最后自增 ID
beginTransaction开始事务
commit提交
rollBack回滚
quote转义字符串(少用,优先预处理)

Transactions

PHP
<?php
$pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

$pdo->beginTransaction();
try {
    $pdo->exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
    $pdo->exec("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
    $pdo->commit();
    echo "转账成功\n";
} catch (Throwable $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    echo "已回滚: " . $e->getMessage() . "\n";
}
Output
转账成功
Check inTransaction() before rollBack(). If the exception came after commit, rolling back throws "no active transaction".

Error information

PHP
<?php
$pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

try {
    $pdo->exec("INSERT INTO users (name, email) VALUES ('A', 'a@e.com')");
} catch (PDOException $e) {
    echo "SQLSTATE: " . $e->getCode() . "\n";
    echo "驱动码: " . ($e->errorInfo[1] ?? "-") . "\n";
    echo "驱动消息: " . ($e->errorInfo[2] ?? "-") . "\n";
}
Output
SQLSTATE: 23000
驱动码: 1062
驱动消息: Duplicate entry 'a@e.com' for key 'uk_email'
SQLSTATEMeaning
23000完整性约束冲突(唯一键、外键、非空)
42S02表不存在
42S22列不存在
42000语法错误或权限不足
HY093参数数量与占位符不符
08006连接失败

Emulated prepares

PHP
<?php
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

echo $pdo->getAttribute(PDO::ATTR_EMULATE_PREPARES) ? "模拟" : "真实服务端预处理", "\n";
Output
真实服务端预处理
In emulation mode PDO builds the SQL client-side — LIMIT ? works but as a string. In native mode it errors. The divergence explains many odd bugs.

Friends & Partners