如果您无法从 PDO 本身获取它,请考虑为 PDOStatement::execute() 使用包装器类,它将记录 SQL 查询和值,然后在语句上调用 execute()。您必须重构代码才能使用新类。
作为旁注,我看到 PDOStatement 有一个类变量 $queryString 保存正在使用的查询。必须从传递给execute() 或bindParam() 的任何内容中检索这些值。
首先是一些用于记录的实用函数:
//removes newlines and extra spaces from print_r output
function str_squeeze($str) {
if (is_array($str)) {
$str = print_r($str, true);
}
$str = preg_replace('/[(\r)?\n|\t]/', ' ', $str);
$str = trim(ereg_replace(' +', ' ', $str));
return $str;
}
function logger($str) {
//log it somewhere
}
选项 1:围绕 PDOStatement 的包装类
class My_PDO_Utils {
public static function execute(PDOStatement &$stm, $values = array()) {
logger("QUERY: " . $stm->queryString . ", values = " . str_squeeze($values)) ;
return $stm->execute($values) ;
}
}
那么你的代码必须是:
$stm = $db->prepare("SELECT * FROM table2 WHERE id = ?") ;
$res = My_PDO_Utils::execute($stm, array(79)) ;
而不是
$res = $stm->execute(array(79)) ;
再想一想,你可以更进一步:
选项 2:扩展 PDO 和 PDOStatement
如果你想冒险,你可以扩展 PDOStatement 来为你做日志记录,并且 PDO 来返回你扩展的 PDOStatement 类。这将需要尽可能少的重构,即只需将new PDO() 更改为new MY_PDO(),但在其实现中可能会变得棘手,因为您需要在 MY_PDOStatement 中明确定义所需的任何 PDOStatement 功能,以便正确调用它。
class My_PDO extends PDO {
public function prepare($sql, $options = array()) {
//do normal call
$stm = parent::prepare($sql, $options) ;
//encapsulate it in your pdostatement wrapper
$myStm = new My_PDOStatement() ;
$myStm->stm = $stm ;
return $myStm ;
}
}
class My_PDOStatement extends PDOStatement {
/**
*
* @var PDOStatement
*/
public $stm ;
public function execute($values) {
logger("QUERY: " . $this->stm->queryString . ", values = " . str_squeeze($values)) ;
return $this->stm->execute($values) ;
}
public function fetchAll($fetch_style = PDO::FETCH_BOTH, $column_index = 0, $ctor_args = array()) {
return $this->stm->fetchAll($fetch_style, $column_index, $ctor_args) ;
}
}
但现在你的代码可以是:
$db = new My_PDO($dsn, $user, $pass) ;
$stm = $db->prepare("SELECT * FROM table2 WHERE id = ?") ;
$res = $stm->execute(array(79)) ;
$row = $stm->fetchAll() ;