
本文详解如何安全、准确地遍历由 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 响应场景。











