
本文详解如何安全、准确地遍历由 json_decode($json, true) 生成的深层嵌套数组,并在 html 表格中逐条渲染物流扫描记录,避免“undefined Array key”和“foreach on NULL”等常见错误。
在 php 中处理 API 返回的 jsON 数据时,使用 json_decode($json, true) 将其转为关联数组是常规做法。但当结构深度较大(如物流追踪数据中包含 ShipmentData → Shipment → Scans → [n] → ScanDetail)时,直接链式访问(如 $item[‘Shipment’][‘Scans’][‘ScanDetail’])极易因键不存在或类型不匹配而触发警告甚至致命错误——正如问题中所示:Warning: Undefined array key “Shipment” 和 foreach() argument must be of type array|Object, null given。
根本原因在于:$item[‘Shipment’][‘Scans’] 是一个索引数组(含多个 [0] => […], [1] => […] 元素),而每个元素内部才是 [‘ScanDetail’] 关联子数组。因此,$item[‘Shipment’][‘Scans’][‘ScanDetail’] 实际试图访问一个不存在的字符串键 ‘ScanDetail’(而非遍历数组),导致返回 null,后续 foreach 即报错。
✅ 正确做法是逐层判断 + 安全遍历。以下是推荐的健壮实现:
$json = file_get_contents('https://track.delhivery.com/api/v1/packages/json/?waybill=&token='); $arr = json_decode($json, true); // 【关键】添加基础结构校验,防止空响应或格式异常 if (!is_array($arr) || !isset($arr['ShipmentData']) || empty($arr['ShipmentData'])) { echo '未获取到有效物流数据,请检查运单号或 Token。
立即学习“PHP免费学习笔记(深入)”;
'; exit; } $items = $arr['ShipmentData']; echo ''; echo '扫描时间 操作状态 扫描地点 状态码 '; echo ''; foreach ($items as $item) { // 确保 Shipment 存在且为数组 if (!isset($item['Shipment']) || !is_array($item['Shipment'])) continue; $shipment = $item['Shipment']; // 确保 Scans 存在且为非空数组 if (!isset($shipment['Scans']) || !is_array($shipment['Scans']) || empty($shipment['Scans'])) continue; // 第一层:遍历 Scans 数组(每个元素是一个含 'ScanDetail' 的子数组) foreach ($shipment['Scans'] as $scan) { // 确保当前 scan 元素包含 'ScanDetail' 且为数组 if (!isset($scan['ScanDetail']) || !is_array($scan['ScanDetail'])) continue; $detail = $scan['ScanDetail']; // 输出单条扫描记录 echo ''; echo '' . htmlspecialchars($detail['ScanDateTime'] ?? 'N/A') . ' '; echo '' . htmlspecialchars($detail['Scan'] ?? 'N/A') . ' '; echo '' . htmlspecialchars($detail['ScannedLocation'] ?? 'N/A') . ' '; echo '' . htmlspecialchars($detail['StatusCode'] ?? 'N/A') . ' '; echo ' '; } } echo '
';
? 关键注意事项:
- 永远不要跳过存在性检查:对每一级嵌套(Shipment、Scans、ScanDetail)都使用 isset() + is_array() 双重验证;
- 使用 htmlspecialchars() 防止 xss:所有输出到 HTML 的动态内容必须转义;
- 用 ?? ‘N/A’ 提供默认值:避免 Notice: Undefined index;
- 避免硬编码键名拼写错误:建议借助 ide 的数组键提示或先用 var_dump(array_keys($arr)) 探查结构;
- 若需调试结构,可用 print_r($arr) 或更友好的
查看完整层级。
通过以上方式,你不仅能解决原始报错,还能构建出稳定、可维护、具备容错能力的 JSON 数据渲染逻辑,适用于各类物流、订单、报表等多维 API 响应场景。