PHP中PDO怎么使用

发布时间:2021-12-20 17:33:29 作者:小新
来源:亿速云 阅读:282
# PHP中PDO怎么使用

## 一、PDO简介

PDO(PHP Data Objects)是PHP中一个轻量级的、兼容性强的数据库操作抽象层。它为访问不同类型的数据库提供了统一的接口,开发者无需针对不同数据库编写特定代码。

### 1.1 PDO核心优势
- **跨数据库兼容性**:支持MySQL、PostgreSQL、SQLite等12+种数据库
- **预处理语句**:内置防止SQL注入的机制
- **面向对象接口**:更符合现代PHP编程范式
- **错误处理**:多种错误模式可选
- **事务支持**:简化复杂数据库操作

### 1.2 与mysql/mysqli扩展对比
| 特性          | PDO            | mysql/mysqli       |
|---------------|----------------|--------------------|
| 数据库支持     | 多数据库        | 仅MySQL           |
| API风格       | 纯面向对象      | 混合风格          |
| 预处理        | 统一语法        | 不同实现          |
| 命名参数      | 支持            | 不支持            |

## 二、PDO基本使用

### 2.1 建立数据库连接

```php
<?php
try {
    $dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';
    $username = 'db_user';
    $password = 'db_pass';
    
    $options = [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES => false,
    ];
    
    $pdo = new PDO($dsn, $username, $password, $options);
} catch (PDOException $e) {
    die("连接失败: " . $e->getMessage());
}

参数说明: - $dsn:数据源名称,格式驱动名:host=主机;dbname=数据库名 - charset:强烈建议设置为utf8mb4以支持完整Unicode - $options常用配置: - ERRMODE_EXCEPTION:错误时抛出异常 - FETCH_ASSOC:默认返回关联数组 - EMULATE_PREPARES:禁用预处理模拟

2.2 执行简单查询

// 查询示例
$stmt = $pdo->query('SELECT * FROM users LIMIT 5');
$results = $stmt->fetchAll();

// 插入示例
$affectedRows = $pdo->exec("
    INSERT INTO users(username, email) 
    VALUES('john', 'john@example.com')
");

三、预处理语句

3.1 防止SQL注入

// 位置参数
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ? AND status = ?");
$stmt->execute([$id, $status]);

// 命名参数
$stmt = $pdo->prepare("
    INSERT INTO products(name, price) 
    VALUES(:name, :price)
");
$stmt->execute([
    ':name' => $productName,
    ':price' => $price
]);

3.2 绑定参数

$stmt = $pdo->prepare("SELECT * FROM posts WHERE category = ?");
$stmt->bindValue(1, $category, PDO::PARAM_STR);
$stmt->execute();

// 绑定输出参数(存储过程)
$stmt = $pdo->prepare("CALL get_user_stats(?, ?)");
$stmt->bindParam(1, $userId, PDO::PARAM_INT);
$stmt->bindParam(2, $output, PDO::PARAM_STR, 100);
$stmt->execute();

四、结果集处理

4.1 获取数据

// 获取单行
$row = $stmt->fetch();

// 获取所有结果
$allRows = $stmt->fetchAll();

// 遍历结果集
while ($row = $stmt->fetch()) {
    echo $row['username'];
}

// 获取单列
$emails = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);

4.2 获取对象

// 获取stdClass对象
$stmt->setFetchMode(PDO::FETCH_OBJ);

// 映射到自定义类
class User {}
$stmt->setFetchMode(PDO::FETCH_CLASS, 'User');

五、事务处理

try {
    $pdo->beginTransaction();
    
    $stmt1 = $pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
    $stmt2 = $pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
    
    $stmt1->execute([$amount, $fromAccount]);
    $stmt2->execute([$amount, $toAccount]);
    
    $pdo->commit();
} catch (Exception $e) {
    $pdo->rollBack();
    echo "事务失败: " . $e->getMessage();
}

六、高级特性

6.1 批量插入

$data = [
    ['name' => 'Product A', 'price' => 9.99],
    ['name' => 'Product B', 'price' => 19.99]
];

$stmt = $pdo->prepare("INSERT INTO products(name, price) VALUES(?, ?)");
foreach ($data as $row) {
    $stmt->execute([$row['name'], $row['price']]);
}

6.2 获取最后插入ID

$pdo->lastInsertId();

6.3 调用存储过程

$stmt = $pdo->prepare("CALL sp_get_user_data(?)");
$stmt->execute([$userId]);

七、错误处理

// 设置错误模式(推荐在连接时设置)
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

try {
    // 数据库操作
} catch (PDOException $e) {
    error_log("数据库错误: " . $e->getMessage());
    // 返回用户友好提示
    echo "系统繁忙,请稍后再试";
}

八、性能优化建议

  1. 持久连接:生产环境考虑使用PDO::ATTR_PERSISTENT
  2. 预处理重用:多次执行时复用预处理语句
  3. 适当使用缓冲查询:大数据集时使用PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
  4. 关闭连接:脚本结束前显式置空$pdo = null

九、完整示例

<?php
class Database {
    private $pdo;
    
    public function __construct() {
        $this->connect();
    }
    
    private function connect() {
        try {
            $this->pdo = new PDO(
                'mysql:host=localhost;dbname=myapp;charset=utf8mb4',
                'db_user',
                'secure_password',
                [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
                ]
            );
        } catch (PDOException $e) {
            die("数据库连接失败: " . $e->getMessage());
        }
    }
    
    public function getUser($userId) {
        $stmt = $this->pdo->prepare("SELECT * FROM users WHERE id = :id");
        $stmt->execute([':id' => $userId]);
        return $stmt->fetch();
    }
    
    public function insertUser($userData) {
        $stmt = $this->pdo->prepare("
            INSERT INTO users(username, email, created_at)
            VALUES(:username, :email, NOW())
        ");
        return $stmt->execute([
            ':username' => $userData['username'],
            ':email' => $userData['email']
        ]);
    }
}

// 使用示例
$db = new Database();
$user = $db->getUser(42);

十、常见问题解答

Q:PDO能防SQL注入吗? A:正确使用预处理语句时可以,但直接拼接SQL仍然危险。

Q:如何获取查询的行数? A:$stmt->rowCount(),但SELECT结果可能不准确,建议使用COUNT查询。

Q:PDO支持哪些数据库? A:完整列表包括MySQL、PostgreSQL、SQLite、Oracle、SQL Server等。

Q:为什么我的预处理语句很慢? A:检查是否禁用了模拟预处理(PDO::ATTR_EMULATE_PREPARES => false

通过本文的全面介绍,您应该已经掌握了PDO的核心用法。在实际开发中,建议将数据库操作封装到单独的类中,以提高代码的可维护性和安全性。 “`

这篇文章约3100字,涵盖了PDO的核心知识点,包括: 1. 基础连接和配置 2. 预处理语句使用 3. 事务处理 4. 结果集操作 5. 性能优化建议 6. 完整封装示例 7. 常见问题解答

采用Markdown格式,包含代码块、表格等元素,便于阅读和理解。可根据需要调整具体细节或补充特定数据库的专有特性。

推荐阅读:
  1. PHP之PDO的使用
  2. PHP中PDO扩展的安装和使用

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

php pdo

上一篇:怎么利用Javascript发送GET/POST请求

下一篇:比原链扩展性UTXO模型是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》