【问题标题】:Overriding fetch() for PDO when fetching using foreach使用 foreach 获取时覆盖 PDO 的 fetch()
【发布时间】:2011-03-20 23:23:47
【问题描述】:

我扩展了PDOStatement 并修改了fetch() 方法以将PostgreSQL 中时间戳和数组类型的值类型转换为日期时间和本机数组。这可以按预期工作,但在 foreach 中使用该语句时我无法覆盖该行为。

我通过将行返回到实现 ArrayAccess、IteratorAggregate 和 Countable 的对象中解决了这个问题。但是我对那个解决方案并不满意,只想要一个纯数组。

例子:

类 ExtendedStatement 扩展 PDOStatement { 受保护的函数 __construct() { $this->setFetchMode(PDO::FETCH_ASSOC); } 公共函数获取( $fetch_style = PDO::FETCH_ASSOC, $cursor_orientation = PDO::FETCH_ORI_NEXT, $cursor_offset = 0) { $r = parent::fetch($fetch_style, $cursor_orientation, $cursor_offset); if (is_array($r)) { $r["额外数据"] = TRUE; } 返回 $r; } } $db = new PDO("sqlite::memory:"); $db->setAttribute( PDO::ATTR_STATEMENT_CLASS, array("ExtendedStatement", array($db))); $db->e​​xec("创建表示例(id INTEGER PRIMARY KEY, name VARCHAR)"); $db->e​​xec("INSERT INTO example(name) VALUES('test')"); // 这就是它的作用 $s = $db->prepare("SELECT * FROM example"); $s->执行(); foreach ($s as $r) { var_dump($r); } $s->closeCursor(); // 这就是我想要的样子 $s = $db->prepare("SELECT * FROM example"); $s->执行(); 而 ($r = $s->fetch()) { var_dump($r); } $s->closeCursor(); // 这就是我想要的样子 $s = $db->prepare("SELECT * FROM example"); $s->执行(); var_dump($s->fetch()); $s->closeCursor();

输出:

数组(2){ [“身份证”]=> 字符串(1)“1” [“名称”]=> 字符串(4)“测试” } 数组(3){ [“身份证”]=> 字符串(1)“1” [“名称”]=> 字符串(4)“测试” [“额外数据”]=> 布尔(真) } 数组(3){ [“身份证”]=> 字符串(1)“1” [“名称”]=> 字符串(4)“测试” [“额外数据”]=> 布尔(真) }

【问题讨论】:

  • 你能展示一些按预期工作但没有按预期工作的代码吗?如果您已覆盖 fetch,它应该始终“正确”工作。
  • 更新了一个例子。
  • while($r = $s->fetch()) {替换foreach是否正常?另外,请记住,parent::fetch 调用返回的结果很可能不是数组,它可能为空。您可能应该添加一个is_array 检查或类似的东西。
  • 是的,它按预期工作。我的正常代码有效,但这开始循环到无穷大。此代码只是演示行为的示例。这不是真正的代码。

标签: php oop pdo php-5.3


【解决方案1】:

PDOStatement 类实现了内置的仅限内部的 Traversable 接口。它实现的迭代器绕过了公共的PDOStatement::fetch() 方法。

【讨论】:

  • 我已经意识到了这一点,但我仍然想以某种方式破解它。我有一个实现迭代器的想法,但为了更好的解决方案而放弃了它。
  • @antennen:嗯,你真的有三个选择:1)补丁ext/pdo/pdo_stmt.c,2)改用while,3)实现你自己的迭代器。无论如何,我可能会建议您在bugs.php.net 提交错误。它应该调用公共的fetch() 方法似乎很合理。
  • 错误报告:bugs.php.net/bug.php?id=52444。我现在可能会尝试自己的迭代器方法。
【解决方案2】:

我使用这样的东西:

$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$sql = 'select * from table';
$stmt = $db->prepare($sql);
$stmt->execute();

while($row = $stmt->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT))
{
    // do stuff
}

所以你唯一需要做的就是设置一些选项:)

【讨论】:

  • 鉴于他的问题示例中已经有这种代码,我很确定他知道这种可能性。
猜你喜欢
  • 2012-08-19
  • 2013-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-01
  • 1970-01-01
  • 2017-12-22
  • 1970-01-01
相关资源
最近更新 更多