foreach要求参数为数组或可遍历对象,传入null或标量会触发致命错误;应使用is_iterable()校验或(array)强转,但需注意语义变化。

foreach 传入 null 或标量值会直接报错
PHP 的 foreach 要求第一个参数必须是数组或对象,如果传了 null、int、string、bool 这类标量,就会抛出 Fatal error: Uncaught TypeError: foreach(): Argument #1 ($array) must be of type array|object。这不是警告,是致命错误,脚本会立刻中断。
常见触发场景包括:数据库查询没结果返回 null、API 接口字段缺失导致变量未定义、函数返回值没做兜底、JSON 解析失败后仍当数组用。
- 检查变量来源:确认它是否来自
json_decode()(默认返回stdClass对象,不是数组)、mysqli_fetch_all()(可能返回false)、$_POST或$_GET中的嵌套键(如$_POST['items']可能根本不存在) - 别依赖“看起来像数组”:
is_array($var) || is_object($var)不够,因为对象还得实现Traversable才能被foreach遍历;更安全的是先判断可遍历性:is_iterable($var)(PHP 7.1+) - 快速修复写法:
foreach ((array) $var as $k => $v)—— 强转成数组能避免报错,但要注意:null 变成空数组,字符串变成单元素数组(['abc']),整数变成[0 => 123],语义可能错乱
json_decode() 返回对象而非数组时不能直接 foreach
默认调用 json_decode($json) 返回的是 stdClass 对象,不是数组,所以 foreach($obj as ...) 会报这个错。很多人只记得加 true 参数,但漏写了。
- 确认 JSON 解析结果:打印
var_dump(json_decode($json)),看是object(stdClass)还是array - 要得到数组,必须显式传
true:json_decode($json, true) - 如果已拿到对象又想遍历,可用
(array) $obj强转,但注意:私有/受保护属性不会被包含,且嵌套对象不会递归转数组 - 更健壮的做法是统一用
is_iterable()判断后再处理:if (is_iterable($data)) { foreach ($data as $item) { /* ... */ } } else { // 处理非可遍历情况,比如记录日志或设默认空数组 $data = []; }
函数返回值未校验就直接 foreach
很多自定义函数(比如查数据库、读配置、调第三方 SDK)在异常或无数据时返回 false、null 或字符串,但调用方直接拿去 foreach,一运行就崩。
- 不要假设函数一定返回数组:哪怕文档写着“返回数组”,也要考虑异常路径(如网络超时、权限拒绝、缓存失效)
- 典型错误写法:
$list = get_user_list(); foreach($list as ...)—— 如果get_user_list()内部return false;,这里就挂了 - 推荐防御式写法:
$list = get_user_list(); if (!is_array($list)) { $list = []; // 或 throw new InvalidArgumentException('Expected array from get_user_list()'); } foreach ($list as $user) { /* ... */ } - 如果函数是你自己写的,建议统一返回空数组而非
false或null,降低调用方心智负担
变量未初始化或作用域错误导致 foreach 用到 undefined
PHP 在未声明变量时访问它,会产生 Notice: Undefined variable,但 foreach 对未定义变量是直接报 TypeError(因为底层把它当作 null 处理)。
- 典型场景:条件分支中只在 if 里赋值,else 没覆盖,之后却在外部
foreach;或者函数内忘记 global / use 引入变量 - 开启
error_reporting(E_ALL)能提前发现未定义变量,但注意:生产环境常关 Notice,所以不能依赖它来拦截foreach错误 - 最稳妥做法:显式初始化变量,尤其是可能被
foreach消费的,例如:$items = [];放在逻辑开始处 - 使用 IDE 或静态分析工具(如 PHPStan)能检测出未初始化变量的使用,比运行时报错更早发现问题
实际项目里最容易被忽略的是「多层嵌套取值后直接 foreach」,比如 $data['response']['items'] —— 这里任意一级键缺失都会让整个表达式变成 null,然后 foreach 就炸了。得一层层判空,或者用 nullsafe 操作符(PHP 8.0+)配合 ?? [] 做兜底。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











