禁用PDO :: ATTR_EMULATE_PREPARES导致“未知”问题

时间:2012-11-16 07:14:42

标签: php mysql pdo

只是一个关于PDO的ATTR_EMULATE_PREPARES属性的简单问题 - 简单地说,当保持默认值(true)时,一切正常,花花公子。然而,禁用它,好吧,我甚至没有收到PHP错误消息,只是一个浏览器警告告诉我“连接已重置”。

这里参考的是我正在使用的代码示例

<?php
include_once("config.php");

try {
  $dbh = new PDO
  (
    "mysql:host=". DB_SERVER .";dbname=" . DB_NAME,
    DB_USER,
    DB_PASS,
    array
    (
      PDO::ATTR_PERSISTENT => true,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
      PDO::ATTR_EMULATE_PREPARES => true
    )
  );
} catch(PDOException $e) {
  echo "<pre>";
  print_r("Error: " . $e);
  echo "</pre>";
  die();
}

$idNum = "1";

$sth = $dbh->prepare("SELECT * FROM `table` WHERE `id` = ?;");
$sth->bindParam(1,$idNum);
$sth->execute();
$res = $sth->fetch();
?>

<pre>
<?=print_r($res); ?>
</pre>

从我可爱的测试表中很好地返回查询...

Array
(
    [id] => 1
    [field1] => q12w3e4r5t6y7u8i9
    [field2] => kijhgbfvcdoikujyh
)

但是,如果我冒昧地将PDO :: ATTR_EMULATE_PREPARES的值设置为false,它将失败,并再次失败,直到我将其返回到其原始值。 我有什么办法可以找出导致这种情况的原因或者我错过了一些非常简单的事情吗?

我的PHP版本目前为5.​​4.3,MySQL为5.5.24

4 个答案:

答案 0 :(得分:5)

这看起来是某些PHP版本中的错误:

https://bugs.php.net/bug.php?id=61411

似乎运行这两个问题

PDO::ATTR_PERSISTENT => true

PDO::ATTR_EMULATE_PREPARES => true

PDO属性/选项数组中包含的内容。

答案 1 :(得分:0)

我遇到了同样的问题,并发现当ATTR_EMULATE_PREPARES = false时可能发生的两个原因:

  1. 如果Select语句包含两个AND / OR操作数,则查询可能会失败。我不得不将它们分为不同的查询。

  2. 如果插入包含bindValue持有者,则ATTR_EMULATE_PREPARES = false对于使这些持有者名称完全匹配更加严格。

答案 2 :(得分:-1)

您好,我想出了如何解决您的(以及我的)问题。

遇到同样的问题,只是连接失败,没有错误。出于某种原因,它不起作用,因为当您调用PDO数据库处理程序的构造函数时,在PDO配置数组中添加了ATTR_EMULATE_PREPARES选项,这会导致PDO崩溃。

当您在没有ATTR_EMULATE_PREPARES选项的情况下启动PDO数据库处理程序然后使用setAttribute禁用仿真时,它将起作用。像这样:

// Configure PDO to really prepare statements and to not emulate them
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

对于刚读这篇文章并想知道为什么如果可能关闭ATTR_EMULATE_PREPARES的人,请阅读: how safe are PDO prepared statements

答案 3 :(得分:-2)

PHP的MYSQL驱动程序并不真正支持预处理语句,它的性能非常差。从禁用mysql的模拟语句可能会出现很多错误。

几天前我刚刚在这个问题上找到了我的头。

有这个:

  

公众在grik dot net 07-Mar-2012 04:23

     

使用PDO_MYSQL,您需要记住PDO :: ATTR_EMULATE_PREPARES选项。

     

默认值为TRUE,如   $ dbh-&GT;的setAttribute(PDO :: ATTR_EMULATE_PREPARES,TRUE);

     

这意味着没有使用$ dbh-&gt; prepare()创建预准备语句   呼叫。使用exec()调用PDO用值替换占位符   本身并向MySQL发送通用查询字符串。

     

第一个结果是调用$ dbh-&gt; prepare('garbage');   报告没有错误。 $ dbh-&gt; exec()期间会出现SQL错误   呼叫。第二个是特殊情况下的SQL注入风险,比如   使用占位符表示表名。

     

仿真的原因是MySQL的性能很差   声明。仿真效果明显加快。

来源:user contributed note