Laravel Blade @foreach报参数无效错误 var_dump显示数组结构正常
问题背景
项目使用 Laravel 5.6.39 版本,业务场景为通过控制器加载Blade视图生成PDF文件,控制器加载视图的代码为:
$pdf = PDF::loadView('direct.tory.here.is.pdf', compact('program', 'taboo', 'colour', 'footnotes'))->setPaper('a4', 'landscape');
异常表现
- 在Blade的@foreach循环中尝试访问数组对应键值时,触发
Invalid argument supplied for foreach()错误。 - 调试过程出现反常现象:在报错的@foreach上一行,使用原生PHP标签输出同一个数组索引的内容时,无任何报错。
- 调试时在疑似异常位置插入测试代码:
@php echo var_dump($item['all']); die(); @endphp
调试输出的正常数组结构如下:
array (size=1)
0 =>
array (size=22)
'withdraw_prod' => int 0
'class_id' => int 10
'optional' => int 0
'extra' => int 0
'stage' => string 'NA' (length=2)
'pest' => string 'NA' (length=2)
'product' => string 'Monitering' (length=10)
'description' => null
'active' => null
'class' => string 'Ander' (length=5)
'rac_code' => null
'htwoo' => string '0' (length=1)
'prod_ha' => string '2.98' (length=4)
'kgl_ha' => string '0.0000' (length=6)
'hundred_met' => null
'total' => string '0.0000' (length=6)
'cost_kgl' => null
'cost_total' => null
'heading' => null
'header' => int 0
'hex' => null
'is_na' => boolean true
- 触发报错的Blade代码为:
@foreach ($item['all'] as $k => $spray) - 对应的Blade编译后原生PHP代码为:
<?php $__currentLoopData = $item['all']; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $k => $spray): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>
视图原始循环逻辑
@foreach ($program as $key => $item) @if(!in_array($key, $taboo)) @php $cnt = 0; $extra_row = 0; //echo var_dump($item['all']); @endphp @foreach ($item['all'] as $k => $spray) @php // 兼容不同维度的数组结构 $sprays = (array_key_exists(0, $spray)) ? $spray[0] : $spray; if(!empty($sprays['description'])) { $extra_row++; } @endphp @endforeach @endif @php $col++; @endphp @endforeach
问题根因与解决
- 根因定位:项目中提前构建了
$taboo键值数组,本意是过滤主数组$program里的非数组元素;但两个月前测试时临时添加的一个整数值类型的虚拟测试键,没有被加入到$taboo过滤列表中。 - 异常传导逻辑:这个未被过滤的整数值绕过了前置判断,导致对应数组索引下不存在
all键,最终传入@foreach循环的并不是合法数组,直接触发报错。 - 调试反常原因:之前加的var_dump测试代码末尾带了
die()中断语句,执行到结构正常的数组分支就直接终止了流程,根本没走到那个缺少all键的异常节点,才会出现“上一行输出正常、下一行循环报错”的矛盾现象。
内容的提问来源于stack exchange,提问作者Hmerman6006

