创建PDO迭代器


Creating PDO Iterator

我将通过这篇文章创建数据库迭代器。我有类似的表格和记录。但是当我执行的时候,我得到的是空白页。我认为$data = new DbRowIterator($stmt);的问题,它没有返回适当的迭代器在FilterIterator类中运行accept方法。我用laravel

这篇文章是一个骗局。它声称提供的技术可以加速使用PDO的数据库调用,但实际上它大大降低了它们的速度。

作为基础的前提也是错误的。PDOStatement 已经是可遍历的,使用foreach遍历PDOStatement不需要任何技巧。

基准测试部分(经常发生)是一个公然的骗局。这个家伙正在比较fetchAll(),这显然消耗了大量的时间/内存,一次只获取一行。即使这样,他的时机也比合适的解决方案糟糕得多。

写这篇文章的家伙不懂PDO,更糟糕的是,不懂SQL。

他发明的一切已经存在在PDO和SQL中:

  1. PDOStatement 已经可遍历。没有必要重新发明轮子。
  2. 最重要的部分:过滤必须在SQL中完成,而不是在PHP中。这是教科书上的规则。如果您只需要250,000条记录中的63992条,那么首先应该只选择63992条。如果你让数据库为你选择记录,它将是无与伦比的快。

所以,要得到这个家伙写的所有东西,你只需要几行PDO

$period = date_create("last_week")->format('Y-m-d 00:00:00');
$sql = 'SELECT * FROM `gen_contact` WHERE contact_modified  > ? ORDER BY `contact_modified` DESC';
$stmt = $pdo->prepare($sql);
$stmt->execute([$period]);
foreach ($stmt as $row) {
    echo sprintf(
        '%s (%s)| modified %s',
        $row->contact_name,
        $row->contact_email,
        $row->contact_modified
    ) . PHP_EOL;
}

和这段代码将是多倍的速度,因为它在数据库级进行过滤,而不是获取整个表,然后在PHP端过滤。

对于您得到的错误,只需将PDO设置为异常模式并观察常规PHP错误。

PDOStatement是不可迭代的,它是可遍历的:
它没有实现'Iterable接口,而是实现了'Traversable接口,这意味着它可以在foreach中使用,但你不能手动迭代它,因为它没有暴露它的内部行为。

我认为这在目前的情况下没有太大的区别,但是两个接口之间仍然有一个主要的区别。

我偶然发现了这个问题,我正在寻找一种方法来正确地遍历PDOStatement(不使用foreach)和文章中提到的,尽管相当笨拙,但对我来说实际上很好。

正如@VincentChalnot所说- PDO不返回Iterable类的实例,但它返回可遍历的实例,并且PHP为可遍历对象提供了一个迭代器- IteratorIterator (http://php.net/manual/en/class.iteratoriterator.php)。

如果你想使用PHP内建的迭代器类,比如缓存迭代器,使用PDOStatement你可以这样做:

$iterator = new CachingIterator(new IteratorIterator($stmt));