我遇到了foreach的一个问题。如果在第一个foreach{foreach $children as $child}
中返回一个结果,则它有效。随着数量的增加,会弹出一个错误:NetteDatabaseResultSet
仅实现单向迭代器。
该错误可能是由在同一表childern
中查询的第一个($children
(和第二个($invoices
(foreach引起的。我需要列出所有子项(例如$child->firstName
(,并为每个子项分配项目(例如$invoice->date
$invoice->snackName
(。然而,我不能取消";CCD_ 9";在查询中。
输出:
子项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;
}
Latte
{block content}
{foreach $children as $child}
{$child->fisrtName}
{foreach $invoices as $invoice}
{invoice->snack}
{/foreach}
{/foreach}
{/block}
您的推理是正确的。大多数NetteDatabase
方法返回的ResultSet
是单向迭代器,因此不能在循环体的多次执行中使用它。这是一种优化——一旦循环推进迭代器,前一行可能会被垃圾收集,这对于节省大型数据库表的内存非常有用。
如果你真的需要多次迭代一个表,你可以:
- 多次创建
$invoices
- 可能将整个赋值移动到模板内的循环中
- 或者创建返回该结果并在模板中调用的函数
- 或者例如通过将整个
ResultSet
转换成阵列来将其加载到存储器中。这也是文档建议的内容:在
ResultSet
上只能迭代一次,如果我们需要迭代多次,则需要通过fetchAll()
方法将结果转换为数组。
但如果可能的话,最好的解决方案是将其修复为使用JOIN
s。如果在数据库中使用FOREIGN KEYS
,则可以避免编写原始SQL,并使用更好的接口,当您尝试通过具有外键约束的列访问其他表中的数据时,该接口将透明高效地为您创建JOIN
。