<p>print_r 处理循环引用会直接崩溃,因无内置循环保护机制,遇自我引用将无限递归直至内存耗尽;var_dump 则自带循环检测,显示 RECURSION 标记,更安全可靠。</p>

print_r 处理循环引用会直接崩溃
当数组或对象存在自我引用(比如 $arr['self'] = &$arr)时,print_r 默认不检测循环,会无限递归直到内存耗尽或触发 PHP 的嵌套层级限制,最终报错 Fatal error: Allowed memory size exhausted 或卡死。它没有内置的循环保护机制。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 绝不在不确定结构是否含循环的场景下直接用
print_r($var) - 若必须用
print_r,先手动检查:用var_dump($var)看一眼顶层结构,确认无引用再切回print_r - PHP 8.0+ 中
print_r加了depth参数(需配合return模式),但依然不防循环,仅限控制展开层数
var_dump 自带循环引用检测和标记
var_dump 从 PHP 5.2 起就内置循环引用识别能力,遇到重复出现的变量会显示 *RECURSION* 而非死循环。这是它比 print_r 更适合调试深层结构的关键原因。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 调试任何可能含引用的对象、数组(如 Laravel 的 Collection、Doctrine Entity 关系)一律首选
var_dump - 注意输出中的
*RECURSION*标记——它不是 bug,是明确告诉你“这里绕回去了”,可据此定位循环点 - 搭配
ini_set('xdebug.var_display_max_depth', 10)可避免过深嵌套干扰判断,但不影响循环检测逻辑
输出格式差异直接影响调试效率
print_r 输出紧凑、无类型标识,适合快速扫视键值对;var_dump 显示类型(int(1)、string(5))、长度、缩进层级,能一眼区分 0 和 false、空字符串和 null。
常见踩坑点:
- 用
print_r查$_POST时看不出字段是 string 还是 array,容易误判表单提交结构 -
print_r对null、false都输出空白行,而var_dump明确写NULL或bool(false) - 在 CLI 下用
print_r查关联数组,键名若含空格或特殊字符,可能被截断或换行错位;var_dump始终用引号包裹字符串键
生产环境日志里别用 var_dump 直接拼接
var_dump 默认输出到标准输出(stdout),若在日志中直接写 error_log(var_dump($data, true)),实际记录的是返回值(null),日志里只留空行。这是因为 var_dump 的返回值始终为 void,即使开了 return 模式也只在第二个参数为 true 时才返回字符串——而它本身不接受该参数作为返回开关。
正确做法只有两个:
- 用
var_export($data, true):生成合法 PHP 代码字符串,可安全写入日志 - 用
json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT):适合结构较平、不含资源/闭包的数据 - 坚持用
print_r($data, true):虽无类型信息,但至少能捕获内容,且兼容性最好
真正难处理的是含资源(如 mysqli 连接)、闭包、不可序列化对象的循环结构——这种时候,得靠 Xdebug 的堆栈快照或手动剥离敏感字段再输出。



















