【问题标题】:Nette framework - Nette\Database\ResultSet implements only one way iteratorNette 框架 - Nette\Database\ResultSet 仅实现一种方式迭代器
【发布时间】:2020-10-31 16:47:13
【问题描述】:

我遇到了 foreach 的问题。 如果在第一个 foreach {foreach $children as $child} 中返回一个结果,则它可以工作。越多,就会弹出一个错误: Nette\Database\ResultSet 只实现一种方式迭代器。

该错误可能是由于在同一个表childern 中查询的第一个($children)和第二个($invoices)foreach 引起的。我需要列出所有孩子(例如$child->firstName)并为每个孩子分配项目(例如$invoice->date$invoice->snackName)。但是,我无法在查询中取消“JOIN ON children”。

输出:

孩子 1 个名字

  • 项目 1
  • 项目 2

孩子 2 的名字

  • 项目 1
  • 项目 2

不知道怎么回事? 谢谢

public function actionShow($year, $month)
 {
    $invoices = $this->database->query('
    SELECT
        o.date AS date,
        o.snack AS snack
    FROM
        diet_orders o
    LEFT JOIN children ch ON o.child_id = ch.id
    WHERE
        ch.user_id = ?
        and YEAR (o.date) = ?
        and MONTH (o.date) = ?
            ', $this->getUser()->id, $year, $month,'');
            $children = $this->database->table('children')->where('user_id = ?', $this->getUser()->id);
    
    $this->template->invoices = $invoices;
    $this->template->children = $children;
}

拿铁

{block content}
{foreach $children as $child}
{$child->fisrtName}
    {foreach $invoices as $invoice}
      {invoice->snack}
     {/foreach}
{/foreach}

{/block}

【问题讨论】:

  • 请更正问题的第二段。它不能完全理解,也不能用英语正确书写。

标签: php nette


【解决方案1】:

你的推理是正确的。大多数Nette\Database 方法返回的ResultSet 是单向迭代器,因此您不能在循环体的多次执行中使用它。这是一种优化——一旦循环推进迭代器,前一行可能会被垃圾回收,这对于节省大型数据库表的内存很有用。

如果您确实需要多次迭代表,您可以:

  • 多次创建$invoices
    • 可能将整个分配移动到模板内的循环中
    • 或创建函数返回该结果并在模板中调用它
  • 或将整个ResultSet 加载到内存中,例如将其转换为数组。这也是documentation 的建议:

    ResultSet以上可以只迭代一次,如果需要多次迭代,则需要通过fetchAll()方法将结果转换为数组。

但如果可能的话,最好的解决方案是将其修复为使用JOINs。如果您在数据库中使用FOREIGN KEYS,则可以避免编写原始SQL,并使用much nicer interface,当您尝试通过具有外部的列访问其他表中的数据时,它将透明且高效地为您创建JOINs键约束。

【讨论】:

  • 谢谢。我在你写的时候使用了fetchAll(),它可以工作。我不明白网络中的JOIN。这就是我编写原始 SQL 的原因。我去看看文档。
猜你喜欢
  • 2023-03-08
  • 2017-06-29
  • 2023-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多