7

只是一个关于 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

4 回答 4

6

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

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

似乎两者都运行有问题

PDO::ATTR_PERSISTENT => true

PDO::ATTR_EMULATE_PREPARES => true

您在 PDO 属性/选项数组中拥有的。

于 2014-09-03T05:50:16.110 回答
0

嗨,我想出了如何解决您(和我的)问题。

遇到同样的问题,只是连接失败,没有错误。由于某种原因它不起作用,因为当您调用 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 的人,请阅读: PDO 准备语句有多安全

于 2013-09-10T11:49:54.320 回答
0

我遇到了同样的问题,并发现当 ATTR_EMULATE_PREPARES = false 时会发生这种情况的两个原因:

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

  2. 如果 Insert 包含 bindValue 持有者,ATTR_EMULATE_PREPARES = false 更严格地使这些持有者名称完全匹配。

于 2019-04-03T19:58:17.967 回答
-2

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

几天前,我刚刚在这个问题上遇到了麻烦。

拥有这个:

在 grik dot net 公开 2012 年 3 月 7 日 04:23

对于 PDO_MYSQL,您需要记住 PDO::ATTR_EMULATE_PREPARES 选项。

默认值为 TRUE,如 $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,true);

这意味着 $dbh->prepare() 调用不会创建任何准备好的语句。使用 exec() 调用 PDO 将占位符替换为值本身,并向 MySQL 发送通用查询字符串。

第一个后果是调用 $dbh->prepare('garbage'); 报告没有错误。您将在 $dbh->exec() 调用期间收到 SQL 错误。第二个是特殊情况下的 SQL 注入风险,例如使用占位符作为表名。

仿真的原因是 MySQL 的预准备语句性能不佳。仿真的工作速度明显更快。

来源:用户提供的注释

于 2012-11-17T19:06:04.107 回答