PHP嵌套foreach循环转Twig遇pieces数据异常,求解决方案
Twig嵌套循环匹配对应pieces数组的问题
我现在要把一段PHP的嵌套foreach逻辑迁移到Twig模板里,单独处理fruit数组没问题,但pieces部分在Twig里只显示case 2的结果,怎么都匹配不上每个fruit对应的id。
我的现有代码
原PHP逻辑代码
$fruit = array(); $fruit[] = array('id' => 1, 'name' => 'Banana 1'); $fruit[] = array('id' => 1, 'name' => 'Pear 1'); $fruit[] = array('id' => 1, 'name' => 'Mango 1'); $fruit[] = array('id' => 2, 'name' => 'Banana 2'); $fruit[] = array('id' => 2, 'name' => 'Pear 2'); $fruit[] = array('id' => 2, 'name' => 'Mango 2'); function get_pieces($id) { $pieces = array(); switch ($id) { case 1: $pieces[] = array('number' => 1); $pieces[] = array('number' => 2); break; case 2: $pieces[] = array('number' => 3); $pieces[] = array('number' => 4, 'qwerty' => 1); break; } return $pieces; } foreach ($fruit as $item) { echo '<p>'; echo '<b>' . $item['name'] . '</b>'; $pieces = get_pieces($item['id']); foreach ($pieces as $piece) { echo '<p>'; echo '<i>' . $piece['number'] . '</i>'; if (isset($piece['qwerty'])) { echo ' => <i>qwerty is on</i>'; } echo '</p>'; } echo '</p>'; }
当前后端传递模板数据的代码
$render = array(); $render = array_merge($render, array('fruit' => $fruit)); $render = array_merge($render, array('pieces' => get_pieces(1))); $render = array_merge($render, array('fruit' => $fruit)); $render = array_merge($render, array('pieces' => get_pieces(2))); echo $twig->render('test.html', $render);
当前Twig模板代码
{% for f in fruit %} <p>{{ f.id }}</p> <p>{{ f.name }}</p> {% for p in pieces %} <p>Piece {{ p.number }}</p> {% endfor %} {% endfor %}
问题分析
你现在的问题很明显——后端传递数据的时候,两次给pieces赋值,第二次get_pieces(2)直接覆盖了第一次的get_pieces(1),所以Twig模板里拿到的永远是id=2的pieces数组,自然没法和每个fruit的id对应起来。
解决方案
方案一:后端预处理,关联每个fruit的pieces
在传递给Twig之前,把每个fruit项对应的pieces直接附加到数组里,这样Twig里直接循环就行:
$render = []; // 预处理fruit数组,给每个项加上对应的pieces foreach ($fruit as &$item) { $item['pieces'] = get_pieces($item['id']); } unset($item); // 解除引用 $render['fruit'] = $fruit; echo $twig->render('test.html', $render);
对应的Twig模板修改为:
{% for f in fruit %} <p><b>{{ f.name }}</b></p> {% for p in f.pieces %} <p><i>{{ p.number }}</i> {% if p.qwerty is defined %} => <i>qwerty is on</i> {% endif %} </p> {% endfor %} {% endfor %}
方案二:在Twig中注册自定义函数,直接调用get_pieces
如果你不想在后端预处理,也可以把get_pieces函数注册到Twig里,这样模板里可以根据当前fruit的id直接调用:
首先在后端注册函数:
// 注册get_pieces函数到Twig $twig->addFunction(new Twig\TwigFunction('get_pieces', 'get_pieces')); $render['fruit'] = $fruit; echo $twig->render('test.html', $render);
然后修改Twig模板:
{% for f in fruit %} <p><b>{{ f.name }}</b></p> {% set pieces = get_pieces(f.id) %} {% for p in pieces %} <p><i>{{ p.number }}</i> {% if p.qwerty is defined %} => <i>qwerty is on</i> {% endif %} </p> {% endfor %} {% endfor %}
内容的提问来源于stack exchange,提问作者Arthur
相关产品推荐
相关产品推荐

