在PHP开发中,数组是最常用的数据结构,而二维数组可以理解为数组中的每个元素本身也是数组。调试时如果直接使用echo输出一个二维数组,往往只会看到一个Array字符串以及一条警告,因为echo期望的是标量类型。为了直观地查看二维数组的键名、层级和值,PHP提供了print_r、var_dump、var_export等内置函数,它们各有侧重,适用于不同的调试场景。下面逐一说明这些方法的用法和区别。

一、print_r函数:快速查看数组结构
print_r是最常用来打印数组的函数,它会递归地展示数组的键和值,输出格式比较紧凑,适合快速浏览数据结构。下面是一个包含用户信息的二维数组示例:
<?php
$users = [
['id' => 1, 'name' => '张三', 'email' => 'zhangsan@ipipp.com'],
['id' => 2, 'name' => '李四', 'email' => 'lisi@ipipp.com'],
['id' => 3, 'name' => '王五', 'email' => 'wangwu@ipipp.com'],
];
print_r($users);
?>
运行这段代码后,终端会输出类似下面的结果,二维数组的层级通过缩进体现出来,第一层是数字索引,第二层是关联键名。可以看出print_r不会显示数据类型,只展示键和值的对应关系,对于确认数组键名是否正确非常方便。
print_r还支持第二个可选参数。当第二个参数设为true时,函数不会直接输出内容,而是把格式化后的字符串作为返回值返回。这个特性很适合把数组结构写入日志文件,或者在拼接字符串时使用。例如把上面的数组信息追加到debug.log文件:
<?php
$dumpText = print_r($users, true);
file_put_contents('debug.log', $dumpText, FILE_APPEND);
?>
在网页环境下,浏览器会忽略普通空格和换行,直接打印print_r的结果会挤在一行,难以阅读。此时可以把输出包裹在<pre>标签中,让浏览器保留原始格式。示例写法是echo '<pre>'; print_r($users); echo '</pre>';。这样二维数组的缩进结构就能在网页上完整展示。
二、var_dump函数:类型和长度信息更全面
var_dump是另一个常用的调试函数,它和print_r最大的不同在于会输出每个值的数据类型和字符串长度。对于二维数组,var_dump会显示外层是array,并标注元素个数,内层数组同样会标注键名、类型和值的长度。下面的代码展示了var_dump的输出效果:
<?php
$matrix = [
[1, 2, 3],
['a', 'b', 'c', 'd'],
[true, false, null],
];
var_dump($matrix);
?>
从输出中可以看到每个整数的类型是int,字符串的类型是string并附带长度,布尔值和null也都有明确标识。这在排查类型转换问题或者确认空值情况时尤其有用。例如数组元素中混合了数字字符串和整数,只有var_dump能清楚显示两者的差异。
var_dump函数本身没有类似print_r第二个参数那样的返回字符串功能,它总是直接把结果输出到标准输出。如果想把var_dump的结果保存下来,可以使用PHP的输出缓冲函数。先用ob_start()开启缓冲,然后调用var_dump,再通过ob_get_clean()获取输出内容并清空缓冲。示例代码如下:
<?php
ob_start();
var_dump($matrix);
$dump = ob_get_clean();
file_put_contents('debug.log', $dump, FILE_APPEND);
?>
需要注意的是,var_dump的输出通常比print_r更冗长,在大型二维数组上直接输出可能产生大量文本。调试时可以针对局部数组片段使用,或者配合die()在输出后终止脚本,避免后续无关内容干扰查看。
三、var_export函数:生成合法的PHP代码
var_export与print_r、var_dump不同,它的目标是输出一段合法的PHP代码,这段代码可以直接被PHP解析执行以还原数组。因此var_export常用于把二维数组保存到配置文件中,之后通过include或eval重新载入。下面是一个简单示例:
<?php
$config = [
'database' => ['host' => '127.0.0.1', 'port' => 3306, 'user' => 'root'],
'cache' => ['driver' => 'redis', 'ttl' => 3600],
];
var_export($config);
?>
输出结果是一个格式整洁的PHP数组字面量,包含方括号和箭头符号,可以直接复制到代码中或者写入文件。var_export也支持第二个参数设为true,从而返回字符串而不是直接输出。例如把配置数组写入config.php文件:
<?php
$configCode = var_export($config, true);
file_put_contents('config.php', '<?php $config = ' . $configCode . ';');
?>
相比print_r和var_dump,var_export的优势在于输出可以被PHP重新读取,适合持久化和生成代码场景。不过它的输出不包含类型标注,对于调试来说信息量略少,一般用于配置文件或缓存文件的生成。读取时使用include即可得到原始数组。
四、json_encode输出与自定义格式化打印
除了内置的数组打印函数,json_encode也经常被用来输出二维数组。它能将数组转换成JSON字符串,这种格式在前后端交互、日志记录以及API调试中非常通用。下面的代码把用户数组转为带缩进的JSON,便于在浏览器或日志工具中查看:
<?php
$users = [
['id' => 1, 'name' => '张三', 'email' => 'zhangsan@ipipp.com'],
['id' => 2, 'name' => '李四', 'email' => 'lisi@ipipp.com'],
];
echo json_encode($users, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
?>
这里使用了两个常用选项:JSON_PRETTY_PRINT让输出带有换行和缩进,JSON_UNESCAPED_UNICODE确保中文字符不会被转义成\u形式。如果直接调用json_encode($users),中文会变成类似\u5f20\u4e09的转义序列,不便于人工阅读。
如果需要在网页中以表格形式展示二维数组,可以编写一个简单的递归或循环函数。例如遍历外层数组,每一行输出一个表格行,内层数组的值作为单元格。下面是一个基本的表格打印函数:
<?php
function printTable(array $data): void {
echo '<table border="1">';
foreach ($data as $row) {
echo '<tr>';
foreach ($row as $cell) {
echo '<td>' . htmlspecialchars((string)$cell) . '</td>';
}
echo '</tr>';
}
echo '</table>';
}
printTable($users);
?>
这个函数假设二维数组的每一行都是关联数组或索引数组,通过两层foreach循环把数据渲染成HTML表格。使用htmlspecialchars对单元格内容进行转义,可以防止数组值中包含HTML标签时破坏页面结构。对于更复杂的数组层级,可以把函数改成递归形式,以处理任意深度的数据。
综合来看,日常调试最常用的还是print_r和var_dump,前者输出简洁,后者信息丰富。需要持久化数组时选择var_export,需要跨语言或前端展示时选择json_encode,而要在网页中呈现规整的二维表结构则可以通过自定义循环实现。根据实际场景灵活选用,能明显提升PHP数组调试和输出的效率。