ZetCode

PHP PDOStatement::setAttribute 方法

最后修改于 2025 年 4 月 19 日

PDOStatement::setAttribute 方法允许为 PDO 预处理语句配置语句级别的属性。它自定义了语句的行为方式。

基本定义

PDOStatement::setAttribute 在语句句柄上设置一个属性。它会影响语句在执行和获取结果时的行为。

语法: public PDOStatement::setAttribute(int $attribute, mixed $value): bool。成功返回 true,失败返回 false。对于无效属性会抛出 PDOException。

设置所有获取的获取模式

此示例演示如何为所有获取操作设置默认获取模式。

set_fetch_mode.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $stmt = $pdo->prepare('SELECT * FROM users');
    $stmt->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    $stmt->execute();
    
    while ($row = $stmt->fetch()) {
        print_r($row);
    }
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

这会将所有获取调用的默认获取模式设置为关联数组。PDO::ATTR_DEFAULT_FETCH_MODE 属性会影响后续的获取操作。

设置游标类型

此示例演示如何为语句执行配置游标类型。

set_cursor_type.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $stmt = $pdo->prepare('SELECT * FROM large_table');
    $stmt->setAttribute(PDO::ATTR_CURSOR, PDO::CURSOR_SCROLL);
    $stmt->execute();
    
    // Scrollable cursor allows fetching rows in any order
    $row = $stmt->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_LAST);
    print_r($row);
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

这会设置一个可滚动的游标,允许对结果行进行随机访问。PDO::CURSOR_SCROLL 允许在执行后按任意顺序获取行。

设置查询超时

此示例演示如何为语句执行设置超时。

set_timeout.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $stmt = $pdo->prepare('SELECT * FROM large_table WHERE complex_condition = ?');
    $stmt->setAttribute(PDO::ATTR_TIMEOUT, 5); // 5 second timeout
    $stmt->execute([1]);
    
    $results = $stmt->fetchAll();
    print_r($results);
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

这会为查询执行设置 5 秒超时。PDO::ATTR_TIMEOUT 属性指定超时(以秒为单位)。并非所有驱动程序都支持此功能。

设置模拟准备

此示例演示如何控制预处理语句的模拟。

set_emulated_prepares.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
    $stmt->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    $stmt->execute([42]);
    
    $user = $stmt->fetch();
    print_r($user);
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

这会禁用模拟准备,强制使用真正的预处理语句。PDO::ATTR_EMULATE_PREPARES=false 在可能的情况下使用本机数据库准备。

设置字符串化获取

此示例演示在获取时将数值转换为字符串。

set_stringify_fetch.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $stmt = $pdo->prepare('SELECT id, name, balance FROM accounts');
    $stmt->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
    $stmt->execute();
    
    $account = $stmt->fetch();
    var_dump($account['balance']); // Will be string even if numeric in DB
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

这会强制将数值作为字符串返回。PDO::ATTR_STRINGIFY_FETCHES 将所有获取的值转换为字符串。对于严格类型检查非常有用。

设置列大小写

此示例演示如何控制结果集中列名的大小写。

set_column_case.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $stmt = $pdo->prepare('SELECT user_id, user_name FROM users');
    $stmt->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
    $stmt->execute();
    
    $user = $stmt->fetch();
    // Column names will be lowercase regardless of database case
    echo $user['user_id']; 
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

这会强制结果集中的列名小写。PDO::ATTR_CASE 与 PDO::CASE_LOWER 一起将所有列名转换为小写。其他选项包括 CASE_UPPER 和 CASE_NATURAL。

设置持久化语句

此示例演示如何使用持久化语句来提高性能。

set_persistent.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password', [
        PDO::ATTR_PERSISTENT => true
    ]);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $stmt = $pdo->prepare('SELECT * FROM frequently_accessed');
    $stmt->setAttribute(PDO::ATTR_STATEMENT_CLASS, ['MyPDOStatement']);
    $stmt->execute();
    
    $results = $stmt->fetchAll();
    print_r($results);
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

class MyPDOStatement extends PDOStatement {
    // Custom statement class for persistent connections
}

这会使用自定义语句类和持久化连接。PDO::ATTR_STATEMENT_CLASS 指定一个自定义语句类。与持久化连接一起使用,以在请求之间保持状态。

最佳实践

来源

PHP PDOStatement::setAttribute 文档

本教程介绍了 PDOStatement::setAttribute 方法,并提供了实际示例,展示了预处理语句的各种配置选项。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 PHP PDO 函数