14

我正在尝试为 PDO 语句的结果编写一个迭代器,但我找不到任何倒回第一行的方法。我想避免调用 fetchAll 并存储所有结果数据的开销。

// first loop works fine
foreach($statement as $result) {
    // do something with result
}

// but subsequent loops don't
foreach($statement as $result) {
    // never called 
}

有没有办法重置语句或寻找第一行?

4

5 回答 5

11

我很确定这取决于数据库。正因为如此,这是你应该尽量避免的事情。但是,我认为您可以通过启用缓冲查询来实现您想要的。如果这不起作用,您始终可以使用fetchAll. 这两种解决方案都会影响您的应用程序性能,因此如果结果集很大,请三思而后行。

于 2008-11-10T18:10:43.453 回答
9

请参阅此演示文稿中的幻灯片 31$statement->rewind() ,如果它适用于缓冲查询,您可以执行此操作。如果您使用 mysql,则可以使用以下命令模拟缓冲查询PDO_MYSQL_ATTR_USE_BUFFERED_QUERY

$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1);

@NoahGoodrich 向您指出 spl。这是一个始终有效的示例:

$it = new ArrayIterator($stmt->fetchAll());
于 2008-11-10T18:46:08.497 回答
9

我写的这个小类包装了一个 PDOStatement。它只存储获取的数据。如果这不起作用,您可以移动缓存以读取和写入文件。

// Wrap a PDOStatement to iterate through all result rows. Uses a 
// local cache to allow rewinding.
class PDOStatementIterator implements Iterator
{
    public
        $stmt,
        $cache,
        $next;

    public function __construct($stmt)
    {
        $this->cache = array();
        $this->stmt = $stmt;
    }

    public function rewind()
    {
        reset($this->cache);
        $this->next();
    }

    public function valid()
    {
        return (FALSE !== $this->next);
    }

    public function current()
    {
        return $this->next[1];
    }

    public function key()
    {
        return $this->next[0];
    }

    public function next()
    {
        // Try to get the next element in our data cache.
        $this->next = each($this->cache);

        // Past the end of the data cache
        if (FALSE === $this->next)
        {
            // Fetch the next row of data
            $row = $this->stmt->fetch(PDO::FETCH_ASSOC);

            // Fetch successful
            if ($row)
            {
                // Add row to data cache
                $this->cache[] = $row;
            }

            $this->next = each($this->cache);
        }
    }
}
于 2013-06-14T06:03:51.250 回答
2

很久以前问过,但目前有另一种解决方案。

该方法可以接收具有常数PDOStatement::fetch()之一的第二参数,即光标方向。这些参数仅在使用as属性创建PDO::FETCH_ORI_*时才有效。PDOStatementPDO::ATTR_CURSORPDO::CURSOR_SCROLL

这样,您可以按如下方式导航。

$sql = "Select * From Tabela";
$statement = $db->prepare($sql, array(
    PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL,
));
$statement->execute();
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_NEXT);  // return next
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_PRIOR); // return previous
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_FIRST); // return first
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_LAST);  // return last
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_ABS, $n); // return to $n position
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_REL, $n); // return to $n position relative to current

文档PDO 预定义常量中的更多信息。

注意:使用PDO::FETCH_BOTH是因为是默认设置,只需为您的项目自定义即可。

于 2016-08-10T14:52:14.917 回答
1

您可能希望了解一些 PHP SPL 类,这些类可以扩展以提供对对象的类似数组的访问。

  • 标准 PHP 库 (SPL)我特别建议您查看 ArrayIterator、ArrayObject,也许还有 Iterator 接口。
  • 简单教程
  • 另一个快速教程
于 2008-11-10T16:20:17.233 回答