
用 var_dump() 看清变量真实结构
想一眼看清一个 PHP 变量到底长啥样——类型、值、嵌套层级、引用关系?var_dump() 是最直接、最可靠的内置函数。它不美化、不过滤、不省略,连 null、resource、循环引用都会如实呈现。
常见错误是拿 echo 或 print_r() 当替代:前者只输出字符串化结果(对象变 Object),后者默认不显示类型、对资源和私有属性支持弱。调试时一旦遇到 array(0) { } 却实际有数据,大概率是没开 display_errors 或用了 print_r() 而没加 true 参数。
- 必须在开发环境使用,生产环境严禁暴露
var_dump()输出 - 输出含 HTML 标签时,建议包裹
<pre class="brush:php;toolbar:false;"></code> 保持缩进:<pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;"><?php var_dump($data); ?></pre> - 调试对象时,
var_dump()会显示所有属性(含 private/protected),比get_object_vars()全面得多
导出结构到文件用 file_put_contents() + var_export()
需要把变量结构保存成可读、可复用的 PHP 代码(比如配置快照、测试数据固化)?var_export() 是唯一选择。它生成的是合法 PHP 语法,返回值可直接 eval() 或写入文件。
注意:var_dump() 是“看”,var_export() 是“存”。后者默认返回字符串,第二个参数设为 true 才返回而非直接输出;而 print_r($var, true) 虽也能捕获输出,但格式不标准、不保证可执行。
立即学习“PHP免费学习笔记(深入)”;
-
var_export($arr, true)返回带类型标注的数组字面量,例如array ( 'a' => 1, ) - 含闭包、资源、不可序列化对象时,
var_export()会报Exception: Unable to export,此时只能退回到serialize()(但结果不可读) - 写入文件务必用
file_put_contents('debug.php', '<?php return ' . var_export($data, true) . ';');,避免裸数据被 Web 服务器直接解析
debug_zval_dump() 查循环引用和引用计数
当 var_dump() 显示 *RECURSION* 或怀疑变量被意外共享修改,就得上 debug_zval_dump()。它会额外打出引用计数(refcount)和是否为引用(is_ref),这是其他函数完全不提供的底层信息。
典型场景:传参后原变量莫名变化、unset() 后内存未释放、协程中变量状态异常。这时候光看值没用,得看 PHP 内部怎么“记账”。
- 输出中的
refcount=2 is_ref=1表示该 zval 被两个变量共用且显式引用(如&$a = $b) - CLI 模式下可用,但 Web SAPI(如 Apache mod_php)可能因输出截断导致信息不全
- PHP 8.0+ 中此函数已被标记为废弃,仅限调试 Zend 引擎行为,日常开发慎用
别踩这些坑:类型陷阱与环境开关
导出结构不是“一调就灵”,三个关键点卡住就白忙:
- 输出被缓冲:开启
ob_start()后,var_dump()内容可能滞留在缓冲区,记得ob_flush()或关掉缓冲 - JSON 不等于结构导出:
json_encode()会丢数据(如 NaN、Inf、资源、私有属性),且强制转字符串,不能替代var_export() - 超大数组/对象容易 OOM:用
ini_set('xdebug.var_display_max_depth', 3)限制var_dump()展开深度,Xdebug 关闭时默认只展 3 层 - CLI 和 Web 的
display_errors默认值不同,Web 下常被静默吞掉错误输出,先确认ini_get('display_errors')是1
真正难的从来不是调哪个函数,而是你得清楚此刻要的是“人眼可读”还是“机器可解析”,以及这个变量里有没有藏着资源、闭包或跨请求的引用。选错函数,后面全是徒劳。











