我在几乎所有项目中都将此函数添加到全局作用域,这使得在浏览器中读取 print_r() 的输出变得容易得多。
<?php
function print_r2($val){
echo '<pre>';
print_r($val);
echo '</pre>';
}
?>
在某些情况下,添加 if 语句以仅在某些情况下显示输出也是有意义的,例如
if(debug==true)
if($_SERVER['REMOTE_ADDR'] == '127.0.0.1')
(PHP 4, PHP 5, PHP 7, PHP 8)
print_r — 打印变量的人类可读信息
示例 #1 print_r() 示例
<pre>
<?php
$a = array ('a' => 'apple', 'b' => 'banana', 'c' => array ('x', 'y', 'z'));
print_r ($a);
?>
</pre>
以上示例将输出
<pre> Array ( [a] => apple [b] => banana [c] => Array ( [0] => x [1] => y [2] => z ) ) </pre>
示例 #2 return
参数示例
<?php
$b = array ('m' => 'monkey', 'foo' => 'bar', 'x' => array ('x', 'y', 'z'));
$results = print_r($b, true); // $results 现在包含 print_r 的输出
?>
注意:
使用
return
参数时,此函数在 PHP 7.1.0 之前使用内部输出缓冲,因此不能在 ob_start() 回调函数中使用。
我在几乎所有项目中都将此函数添加到全局作用域,这使得在浏览器中读取 print_r() 的输出变得容易得多。
<?php
function print_r2($val){
echo '<pre>';
print_r($val);
echo '</pre>';
}
?>
在某些情况下,添加 if 语句以仅在某些情况下显示输出也是有意义的,例如
if(debug==true)
if($_SERVER['REMOTE_ADDR'] == '127.0.0.1')
我已经修复了 Matt 编写的反向 print_r 函数 - 它在空值方面存在问题。也为此创建了一个 GIST,因此请在该处添加任何未来的修复,而不是此评论部分
https://gist.github.com/simivar/037b13a9bbd53ae5a092d8f6d9828bc3
<?php
/**
* Matt: 核心部分
* Trixor: 对象处理
* lech: Windows 支持
* simivar: 空值支持
*
* @see https://php.net/manual/en/function.print-r.php
**/
function print_r_reverse($input) {
$lines = preg_split('#\r?\n#', trim($input));
if (trim($lines[ 0 ]) != 'Array' && trim($lines[ 0 ] != 'stdClass Object')) {
// 递归到底,遇到非数组或对象
if ($input === '') {
return null;
}
return $input;
} else {
// 这是数组或对象,让我们解析它
$match = array();
if (preg_match("/(\s{5,})\(/", $lines[ 1 ], $match)) {
// 这是一个经过测试的数组/对该函数的递归调用
// 去掉开头的一组空格
$spaces = $match[ 1 ];
$spaces_length = strlen($spaces);
$lines_total = count($lines);
for ($i = 0; $i < $lines_total; $i++) {
if (substr($lines[ $i ], 0, $spaces_length) == $spaces) {
$lines[ $i ] = substr($lines[ $i ], $spaces_length);
}
}
}
$is_object = trim($lines[ 0 ]) == 'stdClass Object';
array_shift($lines); // Array
array_shift($lines); // (
array_pop($lines); // )
$input = implode("\n", $lines);
$matches = array();
// 确保我们只匹配前面有 4 个空格的内容(此数组的内容,而不是嵌套的内容)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $input, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($input);
// 在 $pos 中存储以下内容:
// 数组,键 = 解析的数组项的键
// 值 = 数组($in 中的起始位置,$in 中的结束位置)
foreach ($matches as $match) {
$key = $match[ 1 ][ 0 ];
$start = $match[ 0 ][ 1 ] + strlen($match[ 0 ][ 0 ]);
$pos[ $key ] = array($start, $in_length);
if ($previous_key != '') {
$pos[ $previous_key ][ 1 ] = $match[ 0 ][ 1 ] - 1;
}
$previous_key = $key;
}
$ret = array();
foreach ($pos as $key => $where) {
// 递归查看解析出的值是否也是数组
$ret[ $key ] = print_r_reverse(substr($input, $where[ 0 ], $where[ 1 ] - $where[ 0 ]));
}
return $is_object ? (object)$ret : $ret;
}
}
?>
[email protected] 发布了一个函数,该函数将在 HTML 文件中以正确的换行符输出 print_r 的输出结果。他使用了 <pre> 使其生效,但这可能并非始终是最佳方法。例如,在 <p> 内放置 <pre> 是无效的。
这是我的方法
<?php
function print_rbr ($var, $return = false) {
$r = nl2br(htmlspecialchars(print_r($var, true)));
if ($return) return $r;
else echo $r;
}
?>
此函数将
- 在换行符处添加 <br>,
- 使用 HTML 实体转义不安全的字符。
这规避了 print_r 在返回模式下的不稳定特性(对返回模式使用输出缓冲区是一种不稳定的方法……)
<?php
/**
* print_r 的替代函数,与原函数不同的是,它在返回参数设置为 true 时不使用输出缓冲。因此,可以避免在 ob 处理程序中以返回模式使用 print_r 导致的致命错误。
*
* 带有一个额外的参数,可以生成 html 代码。如果您需要一个易于阅读的基于 DHTML 的 print_r 替代方案,请参见 http://krumo.sourceforge.net/
*
* 由 Fredrik Wollsén (fredrik dot motin at gmail) 添加了对对象打印以及 $return 参数功能的支持,使其可以作为 print_r 的直接替换(除了此函数不输出元素组周围的括号… ;) )
*
* 基于 Matthew Ruivo (mruivo at gmail) 编写的 return_array() 函数
* (http://se2.php.net/manual/en/function.print-r.php#73436)
*/
function obsafe_print_r($var, $return = false, $html = false, $level = 0) {
$spaces = "";
$space = $html ? " " : " ";
$newline = $html ? "<br />" : "\n";
for ($i = 1; $i <= 6; $i++) {
$spaces .= $space;
}
$tabs = $spaces;
for ($i = 1; $i <= $level; $i++) {
$tabs .= $spaces;
}
if (is_array($var)) {
$title = "数组";
} elseif (is_object($var)) {
$title = get_class($var)." 对象";
}
$output = $title . $newline . $newline;
foreach($var as $key => $value) {
if (is_array($value) || is_object($value)) {
$level++;
$value = obsafe_print_r($value, true, $html, $level);
$level--;
}
$output .= $tabs . "[" . $key . "] => " . $value . $newline;
}
if ($return) return $output;
else echo $output;
}
?>
基于之前在评论中发布的函数构建。感谢!/Fredrik (Motin)
我的代码中一直使用此函数,因为我的大多数函数都返回数组或布尔值。
<?php
function printr ( $object , $name = '' ) {
print ( '\'' . $name . '\' : ' ) ;
if ( is_array ( $object ) ) {
print ( '<pre>' ) ;
print_r ( $object ) ;
print ( '</pre>' ) ;
} else {
var_dump ( $object ) ;
}
}
?>
(print_r 对 FALSE 不输出任何内容,这可能会很烦人!)
对 Matt 的出色 print_r_reverse 函数进行了一些修改(谢谢,救星 - 数据恢复 :-) 。如果输出是从 Windows 系统复制的,则行尾可能包含回车符“\r”,因此标量(字符串)元素将包含不应该存在的尾随“\r”字符。要解决此问题,请将函数中的第一行替换为…
<?php $lines = preg_split('#\r?\n#', trim($in)); ?>
这适用于 Linux 和 Windows 系统。
为了完整起见,我在下面包含了整个函数,但所有功劳都归于原始作者 Matt,谢谢。
<?php
//作者:Matt (http://us3.php.net/print_r)
function print_r_reverse($in) {
$lines = preg_split('#\r?\n#', trim($in));
if (trim($lines[0]) != 'Array') {
// 已经解析到不是数组的元素
return $in;
} else {
// 这是一个数组,让我们解析它
if (preg_match("/(\s{5,})\(/", $lines[1], $match)) {
// 这是一个已测试的数组/对该函数的递归调用
// 去除开头的一组空格
$spaces = $match[1];
$spaces_length = strlen($spaces);
$lines_total = count($lines);
for ($i = 0; $i < $lines_total; $i++) {
if (substr($lines[$i], 0, $spaces_length) == $spaces) {
$lines[$i] = substr($lines[$i], $spaces_length);
}
}
}
array_shift($lines); // Array
array_shift($lines); // (
array_pop($lines); // )
$in = implode("\n", $lines);
// 确保我们只匹配前面有4个空格的内容(该数组的内容,而不是嵌套的内容)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $in, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($in);
// 在$pos中存储以下内容:
// 数组,键=已解析数组项的键
// 值=数组($in中的起始位置,$in中的结束位置)
foreach ($matches as $match) {
$key = $match[1][0];
$start = $match[0][1] + strlen($match[0][0]);
$pos[$key] = array($start, $in_length);
if ($previous_key != '') $pos[$previous_key][1] = $match[0][1] - 1;
$previous_key = $key;
}
$ret = array();
foreach ($pos as $key => $where) {
// 递归查看解析出的值是否也是数组
$ret[$key] = print_r_reverse(substr($in, $where[0], $where[1] - $where[0]));
}
return $ret;
}
}
?>
这是一个解析print_r()输出的另一个版本。我尝试过发布的那个,但是遇到了困难。我相信它在嵌套数组方面存在问题。据我所知,这个版本可以无问题地处理嵌套数组。
<?php
function print_r_reverse($in) {
$lines = explode("\n", trim($in));
if (trim($lines[0]) != 'Array') {
// 遇到非数组类型则返回
return $in;
} else {
// 这是一个数组,进行解析
if (preg_match("/(\s{5,})\(/", $lines[1], $match)) {
// 这是一个经过测试的数组/递归调用此函数
// 去除开头的一组空格
$spaces = $match[1];
$spaces_length = strlen($spaces);
$lines_total = count($lines);
for ($i = 0; $i < $lines_total; $i++) {
if (substr($lines[$i], 0, $spaces_length) == $spaces) {
$lines[$i] = substr($lines[$i], $spaces_length);
}
}
}
array_shift($lines); // 删除 'Array'
array_shift($lines); // 删除 '('
array_pop($lines); // 删除 ')'
$in = implode("\n", $lines);
// 确保只匹配前面有4个空格的内容(此数组的内容,而不是嵌套数组)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $in, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($in);
// 将以下内容存储在 $pos 中:
// 数组,键 = 解析的数组项的键
// 值 = 数组($in 中的起始位置,$in 中的结束位置)
foreach ($matches as $match) {
$key = $match[1][0];
$start = $match[0][1] + strlen($match[0][0]);
$pos[$key] = array($start, $in_length);
if ($previous_key != '') $pos[$previous_key][1] = $match[0][1] - 1;
$previous_key = $key;
}
$ret = array();
foreach ($pos as $key => $where) {
// 递归查看解析出的值是否也是数组
$ret[$key] = print_r_reverse(substr($in, $where[0], $where[1] - $where[0]));
}
return $ret;
}
}
?>
print_r(),就像 var_dump() 一样,不会强制转换对象,即使对象具有 __toString() 方法也是如此 - 这很正常。
<?php
class A {
public function __toString() {
return 'In class A';
}
}
$a = new A;
echo $a; // In class A
print_r($a); // A Object()
// 可以通过手动转换来模拟 echo
print_r((string)$a); // In class A
对前面帖子的一个小修改,允许数组包含多行字符串。我没有用所有情况完全测试它,但它似乎在我的测试中运行良好。
<?php
function print_r_reverse(&$output)
{
$expecting = 0; // 0=无特殊值,1=数组左括号 '(',2=数组元素或右括号 ')'
$lines = explode("\n", $output);
$result = null;
$topArray = null;
$arrayStack = array();
$matches = null;
while (!empty($lines) && $result === null)
{
$line = array_shift($lines);
$trim = trim($line);
if ($trim == 'Array')
{
if ($expecting == 0)
{
$topArray = array();
$expecting = 1;
}
else
{
trigger_error("未知数组.");
}
}
else if ($expecting == 1 && $trim == '(')
{
$expecting = 2;
}
else if ($expecting == 2 && preg_match('/^\[(.+?)\] \=\> (.+)$/', $trim, $matches)) // 数组元素
{
list ($fullMatch, $key, $element) = $matches;
if (trim($element) == 'Array')
{
$topArray[$key] = array();
$newTopArray =& $topArray[$key];
$arrayStack[] =& $topArray;
$topArray =& $newTopArray;
$expecting = 1;
}
else
{
$topArray[$key] = $element;
}
}
else if ($expecting == 2 && $trim == ')') // 结束当前数组
{
if (empty($arrayStack))
{
$result = $topArray;
}
else // 弹出到父数组
{
// 安全的数组弹出
$keys = array_keys($arrayStack);
$lastKey = array_pop($keys);
$temp =& $arrayStack[$lastKey];
unset($arrayStack[$lastKey]);
$topArray =& $temp;
}
}
// 添加此行以允许多行字符串。
else if (!empty($trim) && $expecting == 2)
{
// 期望右括号或元素,但只得到一个字符串
$topArray[$key] .= "\n".$line;
}
else if (!empty($trim))
{
$result = $line;
}
}
$output = implode(n, $lines);
return $result;
}
/**
* @param string $output : 多个 print_r 调用的输出,用换行符分隔
* @return mixed[] : $output 中可解析的元素
*/
function print_r_reverse_multiple($output)
{
$result = array();
while (($reverse = print_r_reverse($output)) !== NULL)
{
$result[] = $reverse;
}
return $result;
}
$output = '
Array
(
[a] => apple
[b] => banana
[c] => Array
(
[0] => x
[1] => y
[2] => z
[3] => Array
(
[nest] => yes
[nest2] => Array
(
[nest] => some more
asffjaskkd
)
[nest3] => o rly?
)
)
)
some extra stuff
';
var_dump(print_r_reverse($output), $output);
?>
预期输出
array(3) {
["a"]=>
string(5) "apple"
["b"]=>
string(6) "banana"
["c"]=>
array(4) {
[0]=>
string(1) "x"
[1]=>
string(1) "y"
[2]=>
string(1) "z"
[3]=>
array(3) {
["nest"]=>
string(3) "yes"
["nest2"]=>
array(1) {
["nest"]=>
string(40) "some more
asffjaskkd"
}
["nest3"]=>
string(6) "o rly?"
}
}
}
string(18) "nsome extra stuffn"
添加
else if (!empty($trim) && $expecting == 2)
{
// 期望右括号或元素,但只得到一个字符串
$topArray[$key] .= "\n".$line;
}
这是一个生成 XML 的 print_r 函数
(现在您可以在浏览器中展开/折叠节点)
<?php
header('Content-Type: text/xml; charset=UTF-8');
echo print_r_xml($some_var);
function print_r_xml($arr,$first=true) {
$output = "";
if ($first) $output .= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<data>\n";
foreach($arr as $key => $val) {
if (is_numeric($key)) $key = "arr_".$key; // <0 不允许
switch (gettype($val)) {
case "array":
$output .= "<".htmlspecialchars($key)." type='array' size='".count($val)."'>".
print_r_xml($val,false)."</".htmlspecialchars($key).">\n"; break;
case "boolean":
$output .= "<".htmlspecialchars($key)." type='bool'>".($val?"true":"false").
"</".htmlspecialchars($key).">\n"; break;
case "integer":
$output .= "<".htmlspecialchars($key)." type='integer'>".
htmlspecialchars($val)."</".htmlspecialchars($key).">\n"; break;
case "double":
$output .= "<".htmlspecialchars($key)." type='double'>".
htmlspecialchars($val)."</".htmlspecialchars($key).">\n"; break;
case "string":
$output .= "<".htmlspecialchars($key)." type='string' size='".strlen($val)."'>".
htmlspecialchars($val)."</".htmlspecialchars($key).">\n"; break;
default:
$output .= "<".htmlspecialchars($key)." type='unknown'>".gettype($val).
"</".htmlspecialchars($key).">\n"; break;
}
}
if ($first) $output .= "</data>\n";
return $output;
}
?>
对于非常长的数组,我编写了一个小函数,它可以很好地格式化数组,并使用 JavaScript 像树一样浏览它。该函数可以通过 $style 参数进行高度自定义。
对我来说,它非常适合浏览大型数组,例如在某些脚本的语言文件中使用这些数组时等等。它甚至可以用于“真实”脚本的“真实”前端,因为树可以非常容易地进行样式设置(查看函数或输出的源代码,你就会明白我的意思)。
这是函数代码:
<?php
function print_r_html($arr, $style = "display: none; margin-left: 10px;")
{ static $i = 0; $i++;
echo "\n<div id=\"array_tree_$i\" class=\"array_tree\">\n";
foreach($arr as $key => $val)
{ switch (gettype($val))
{ case "array":
echo "<a onclick=\"document.getElementById('";
echo array_tree_element_$i."').style.display = ";
echo "document.getElementById('array_tree_element_$i";
echo "').style.display == 'block' ?";
echo "'none' : 'block';\"\n";
echo "name=\"array_tree_link_$i\" href=\"#array_tree_link_$i\">".htmlspecialchars($key)."</a><br />\n";
echo "<div class=\"array_tree_element_\" id=\"array_tree_element_$i\" style=\"$style\">";
echo print_r_html($val);
echo "</div>";
break;
case "integer":
echo "<b>".htmlspecialchars($key)."</b> => <i>".htmlspecialchars($val)."</i><br />";
break;
case "double":
echo "<b>".htmlspecialchars($key)."</b> => <i>".htmlspecialchars($val)."</i><br />";
break;
case "boolean":
echo "<b>".htmlspecialchars($key)."</b> => ";
if ($val)
{ echo "true"; }
else
{ echo "false"; }
echo "<br />\n";
break;
case "string":
echo "<b>".htmlspecialchars($key)."</b> => <code>".htmlspecialchars($val)."</code><br />";
break;
default:
echo "<b>".htmlspecialchars($key)."</b> => ".gettype($val)."<br />";
break; }
echo "\n"; }
echo "</div>\n"; }
?>
目前这个函数不支持像 print_r 一样的 $return 参数,并且当存在包含对要打印的数组内变量的引用的元素时,它会像 PHP 4.0.3 之前的版本中的 print_r 一样产生无限循环 :-/。
我已经用 PHP 5.0.6 和 PHP 4.2.3 测试过它了——除了上面提到的问题之外,没有其他问题。
如果您找到了我提到的问题的解决方案,请给我发邮件,我自己无法解决它们,因为我不知道该如何判断一个变量是否是引用。
print_r 用于调试目的。但是我有一些类,我只想要从数据库中出来的值,而不是所有其他的东西。因此,我编写了以下函数。如果你的类有 toArray 函数,则会调用该函数,否则它将按原样返回对象。应该调用 print_neat_classes_r 函数!
<?php
print_neat_classes_r($array, $return=false){
return print_r(self::neat_class_print_r($array), $return);
}
function do_print_r($array, $return=false){
if(is_object($array) && method_exists($array, 'toArray')){
return $array->toArray();
}else if(is_array($array)){
foreach($array as $key=>$obj){
$array[$key] = self::do_print_r($obj, $return);
}
return $array;
}else{
return $array;
}
}
?>
这是一个函数,它使用 HTML 和 JavaScript 将 print_r 的输出格式化为可展开/可折叠的树状列表。
<?php
function print_r_tree($data)
{
// 获取 print_r 的输出
$out = print_r($data, true);
// 将类似于 '[element] => (' 的内容替换为 <a href="javascript:toggleDisplay('...');">...</a><div id="..." style="display: none;">
$out = preg_replace('/([ \t]*)(\[[^\]]+\][ \t]*\=\>[ \t]*[a-z0-9 \t_]+)\n[ \t]*\(/iUe',"'\\1<a href=\"javascript:toggleDisplay(\''.(\$id = substr(md5(rand().'\\0'), 0, 7)).'\');\">\\2</a><div id=\"'.\$id.'\" style=\"display: none;\">'", $out);
// 将单独位于新行上的 ')'(周围允许有空格)替换为 '</div>
$out = preg_replace('/^\s*\)\s*$/m', '</div>', $out);
// 打印 JavaScript 函数 toggleDisplay(),然后打印转换后的输出
echo '<script language="Javascript">function toggleDisplay(id) { document.getElementById(id).style.display = (document.getElementById(id).style.display == "block") ? "none" : "block"; }</script>'."\n$out";
}
?>
将多维数组或对象传递给它,每个子数组/对象都将被隐藏,并替换为一个 HTML 链接,该链接将切换其显示状态。
它又快又脏,但对于调试大型数组和对象的内容非常有用。
注意:你可能需要用 <pre></pre> 括住输出。
以下代码将以 PHP 可解析的格式输出数组。
<?php
function serialize_array(&$array, $root = '$root', $depth = 0)
{
$items = array();
foreach($array as $key => &$value)
{
if(is_array($value))
{
serialize_array($value, $root . '[\'' . $key . '\']', $depth + 1);
}
else
{
$items[$key] = $value;
}
}
if(count($items) > 0)
{
echo $root . ' = array(';
$prefix = '';
foreach($items as $key => &$value)
{
echo $prefix . '\'' . $key . '\' => \'' . addslashes($value) . '\'';
$prefix = ', ';
}
echo ');' . "\n";
}
}
?>
我写了一个不错的调试函数。
此函数可以完美地处理数组。
<?php
//调试变量,$i 和 $k 用于递归使用
function DebugDisplayVar($input, $name = "Debug", $i = "0", $k = array("Error")){
if(is_array($input))
{ foreach ($input as $i => $value){
$temp = $k;
$temp[] = $i;
DebugDisplayVar($value, $name, $i, $temp);}
}else{//如果不是数组
echo "$".$name;//[$k]
foreach ($k as $i => $value){
if($value !=="Error"){echo "[$value]";}
}
echo " = $input<br>";
} }
//输出
Debug[0] = value
Debug[1] = 另一个值
等等...
?>
对于那些需要在缓冲回调函数中打印数组的人,我创建了这个快速函数。它只是将数组作为可读字符串返回,而不是打印它。你甚至可以选择是否以普通文本模式或 HTML 模式返回它。它是递归的,因此支持多维数组。我希望有人觉得这个有用!
<?php
function return_array($array, $html = false, $level = 0) {
$space = $html ? " " : " ";
$newline = $html ? "<br />" : "\n";
for ($i = 1; $i <= 6; $i++) {
$spaces .= $space;
}
$tabs = $spaces;
for ($i = 1; $i <= $level; $i++) {
$tabs .= $spaces;
}
$output = "Array" . $newline . $newline;
foreach($array as $key => $value) {
if (is_array($value)) {
$level++;
$value = return_array($value, $html, $level);
$level--;
}
$output .= $tabs . "[" . $key . "] => " . $value . $newline;
}
return $output;
}
?>