警告源于foreach接收非数组值,需先var_dump($data)定位类型;推荐is_array($items) && !empty($items)双重校验,避免误判;强制(array)转换有风险,慎用。

foreach 报 Warning: Invalid argument supplied for foreach() 怎么快速定位
这个警告不是语法错误,而是运行时提示:你传给 foreach 的变量根本就不是数组——可能是 null、false、string、int,甚至未定义的变量(undefined variable)。常见于数据库查询失败、API 返回异常、配置读取为空、函数返回值没校验等场景。
别急着改循环体,先确认 $data 到底是什么:
- 在
foreach前加一行var_dump($data); die;,看输出类型和值 - 检查上游逻辑:比如
$data = $db->fetchList();是否可能返回false或null? - 注意 PHP 8+ 对未初始化变量的严格性:直接用
$items而没声明,会触发 Notice,进而让foreach收到null
最稳妥的写法:用 is_array() + empty() 双重判断
只靠 is_array() 不够——空数组 [] 是合法的,但有时你确实不想进循环;而 empty() 会把非空字符串、数字 0 也判为真,所以必须组合使用。
推荐这样写:
立即学习“PHP免费学习笔记(深入)”;
if (is_array($items) && !empty($items)) {
foreach ($items as $item) {
// 安全执行
}
}
注意点:
-
!empty($items)在 PHP 7.3+ 中对空数组返回true,行为稳定 - 不要只写
if ($items):0、"0"、false都会跳过,误伤合法数据 - 如果业务允许遍历空数组(比如渲染空列表),那就只留
is_array()判断即可
强制转数组:(array) 强转的适用与风险
foreach ((array)$items as $item) 看似简洁,但它会把几乎所有东西都“塞”进数组:
-
null→[](安全) -
false→[false](可能意外触发循环一次) -
42→[42](数字变单元素数组) -
"hello"→(字符串也变数组)</li> </ul> <p>所以它适合「你确定上游只会返回标量或 null,且能接受这种隐式转换」的简单场景。比如模板层处理一个不确定是否存在的配置项:</p> <pre class="brush:php;toolbar:false;">foreach ((array)$config['tags'] as $tag) { echo $tag; }但绝不该用于数据库结果集、API 响应体这类结构敏感的数据——
(array)false 得到 <code>[false],后续访问$tag['id']又会报错。更深层的问题:为什么 $data 不是数组?
补判断只是止痛,真正要查的是源头。高频原因包括:
- 数据库查询失败没做错误处理,
mysqli_fetch_all()返回null - JSON 解码失败:
json_decode($json, true)遇到非法 JSON 时返回null - 函数文档说「返回数组」,实际可能返回
false(如glob()找不到文件) - PHP 8.1+ 启用了
strict_types=1,但某个函数声明返回array却悄悄返回了null
建议在关键数据入口统一加断言或日志,比如:
$data = get_user_list(); if (!is_array($data)) { error_log('get_user_list() returned non-array: ' . var_export($data, true)); $data = []; }真正的坑不在
foreach这一行,而在它上面三行没校验的那句函数调用。 - 数据库查询失败没做错误处理,



















