微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Nette框架-​​Nette \ Database \ ResultSet仅实现一种迭代器

如何解决Nette框架-​​Nette \ Database \ ResultSet仅实现一种迭代器

我遇到了foreach问题。 如果在第一个foreach {foreach $children as $child}中返回了一个结果,那么它将起作用。随着更多信息的出现,将弹出一个错误Nette\Database\ResultSet仅实现一种迭代器。

错误可能是由于在同一个$children查询的每个($invoices)和第二个(childern)引起的。我需要列出所有子项(例如$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}

解决方法

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

如果确实需要多次遍历一个表,则可以:

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。