0

在 PDO 中使用 bindParam 或 bindValue 时,PDOStatement 对象中的“绑定”究竟存储在哪里?是否可以显示此设置属性/参考/等?

我试图了解这些和其他 PDOStatement 方法在 PDOStatement 对象中存储/定位它们的数据的位置(如果甚至可以在通过 PDOStatement 方法设置之外访问它)。

(我想这个问题也延伸到其他 PDO/PDOStatement 方法,很好奇东西存储在哪里,比如是否进入属性或诸如此类)

4

1 回答 1

1

准备好的语句要么是协议功能(例如 mysql),要么将在幕后的 C 库中运行。这意味着解析语句的工作不是由 PDO 代码完成的。它由数据库服务器或 libsqlite 等 C 库完成。由于 PDO 本身不解析语句,只是将其传递给较低级别​​的组件,因此参数信息对它不可用。

因此,使用普通 PHP 无法使用 PDOStatement 对象将关联占位符 =>替换为查询中的值。这是预先准备好的声明的设计。

一种解决方法可能是扩展PDOStatement并添加一个方法,用当前查询字符串中的值替换参数占位符。我在下面准备了一个例子。请注意,此示例不是防弹的,例如,:bar即使它出现在带引号的字符串中,它也会替换。但是对于内部使用,到目前为止,像这样的解决方案对我来说做得很好。

自定义语句类:

class MyStatement extends PDOStatement
{

    protected $params;
    protected $pdo;

    protected function __construct($pdo) {
        $this->pdo = $pdo;
    }

    public function execute($params = null) {
        $this->params = $params;
        return parent::execute($params);
    }


    public function printQuery(){
        $_params = $this->params;
        $sql = $this->queryString;
        foreach($this->params as $key => $value) {
            $_value = is_null($value) ?
                'NULL' : '\'' . $value . '\'';
            $sql = str_replace(':'. $key, $_value, $sql);
        }
        return $sql;
    }
}

您需要修改后的 PDO

class MyPDO extends PDO
{

    public function __construct($dsn, $username="", $password="", $driver_options=array()) {
        parent::__construct($dsn, $username, $password, array(
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_STATEMENT_CLASS => array('MyStatement', array($this))
        ));
    }
}

测试代码:

$pdo = new MyPDO('mysql:host=localhost;dbname=test', 'root', '******');

// preapre stupid query
$stmt = $pdo->prepare('SELECT FROM `foo` WHERE name = :bar');

try {
    // execute stmt
    $stmt->execute(array('bar' => 'hek2mgl'));
} catch (PDOException $e) {
    echo $stmt->printQuery();
}
于 2013-07-17T21:43:40.740 回答