我在幾乎每個專案中都會將此函式添加到全域範圍,這讓在瀏覽器中閱讀 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 — 以人類可讀的格式印出變數的相關資訊
print_r() 以人類可讀的方式顯示變數的相關資訊。
print_r()、var_dump() 和 var_export() 也會顯示物件的 protected 和 private 屬性。靜態類別成員將不會顯示。
範例 #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: core
* Trixor: object handling
* lech: Windows suppport
* simivar: null support
*
* @see https://php.dev.org.tw/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')) {
// bottomed out to something that isn't an array or object
if ($input === '') {
return null;
}
return $input;
} else {
// this is an array or object, lets parse it
$match = array();
if (preg_match("/(\s{5,})\(/", $lines[ 1 ], $match)) {
// this is a tested array/recursive call to this function
// take a set of spaces off the beginning
$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();
// make sure we only match stuff with 4 preceding spaces (stuff for this array and not a nested one)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $input, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($input);
// store the following in $pos:
// array with key = key of the parsed array's item
// value = array(start position in $in, $end position 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) {
// recursively see if the parsed out value is an array too
$ret[ $key ] = print_r_reverse(substr($input, $where[ 0 ], $where[ 1 ] - $where[ 0 ]));
}
return $is_object ? (object)$ret : $ret;
}
}
?>
liamtoh6@hotmail.com 發佈了一個函式,它將在 HTML 檔案中以正確的換行符號顯示 print_r 輸出。他使用 <pre> 來實現這一點,但这可能並非總是最佳方法。例如,將 <pre> 放在 <p> 內是無效的。
這是我的做法
<?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 在返回模式下的 hacky 特性(使用輸出緩衝來使返回模式工作是一種 hacky 的做法……)
<?php
/**
* An alternative to print_r that unlike the original does not use output buffering with
* the return parameter set to true. Thus, Fatal errors that would be the result of print_r
* in return-mode within ob handlers can be avoided.
*
* Comes with an extra parameter to be able to generate html code. If you need a
* human readable DHTML-based print_r alternative, see http://krumo.sourceforge.net/
*
* Support for printing of objects as well as the $return parameter functionality
* added by Fredrik Wollsén (fredrik dot motin at gmail), to make it work as a drop-in
* replacement for print_r (Except for that this function does not output
* paranthesises around element groups... ;) )
*
* Based on return_array() By Matthew Ruivo (mruivo at gmail)
* (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 = "Array";
} elseif (is_object($var)) {
$title = get_class($var)." Object";
}
$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;
}
?>
基於先前在此註釋中發佈的函式構建,如 Doc 註釋中所述。 乾杯!/Fredrik (Motin)
我總是在我的程式碼中使用這個函式,因為我的大多數函式都返回一個陣列或布林值。
<?php
function printr ( $object , $name = '' ) {
print ( '\'' . $name . '\' : ' ) ;
if ( is_array ( $object ) ) {
print ( '<pre>' ) ;
print_r ( $object ) ;
print ( '</pre>' ) ;
} else {
var_dump ( $object ) ;
}
}
?>
(如果傳入 FALSE,print_r 不會輸出任何東西,這可能會造成困擾!)
對 Matt 出色的 print_r_reverse 函式做了一點小修正(謝謝你,救星 - 資料恢復 :-))。如果輸出是從 Windows 系統複製的,則行尾可能包含回車字元 "\r",因此純量(字串)元素將包含一個不應該出現的尾端 "\r" 字元。要解決此問題,請將函式中的第一行替換為...
<?php $lines = preg_split('#\r?\n#', trim($in)); ?>
這適用於兩種情況(Linux 和 Windows)。
為了完整性,我在下面包含了整個函式,但所有功勞都歸於原作者 Matt,謝謝你。
<?php
//Author: Matt (http://us3.php.net/print_r)
function print_r_reverse($in) {
$lines = preg_split('#\r?\n#', trim($in));
if (trim($lines[0]) != 'Array') {
// bottomed out to something that isn't an array
return $in;
} else {
// this is an array, lets parse it
if (preg_match("/(\s{5,})\(/", $lines[1], $match)) {
// this is a tested array/recursive call to this function
// take a set of spaces off the beginning
$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);
// make sure we only match stuff with 4 preceding spaces (stuff for this array and not a nested one)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $in, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($in);
// store the following in $pos:
// array with key = key of the parsed array's item
// value = array(start position in $in, $end position 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) {
// recursively see if the parsed out value is an array too
$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') {
// bottomed out to something that isn't an array
return $in;
} else {
// this is an array, lets parse it
if (preg_match("/(\s{5,})\(/", $lines[1], $match)) {
// this is a tested array/recursive call to this function
// take a set of spaces off the beginning
$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);
// make sure we only match stuff with 4 preceding spaces (stuff for this array and not a nested one)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $in, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($in);
// store the following in $pos:
// array with key = key of the parsed array's item
// value = array(start position in $in, $end position 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) {
// recursively see if the parsed out value is an array too
$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=nothing in particular, 1=array open paren '(', 2=array element or close paren ')'
$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("Unknown array.");
}
}
else if ($expecting == 1 && $trim == '(')
{
$expecting = 2;
}
else if ($expecting == 2 && preg_match('/^\[(.+?)\] \=\> (.+)$/', $trim, $matches)) // array element
{
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 == ')') // end current array
{
if (empty($arrayStack))
{
$result = $topArray;
}
else // pop into parent array
{
// safe array pop
$keys = array_keys($arrayStack);
$lastKey = array_pop($keys);
$temp =& $arrayStack[$lastKey];
unset($arrayStack[$lastKey]);
$topArray =& $temp;
}
}
// Added this to allow for multi line strings.
else if (!empty($trim) && $expecting == 2)
{
// Expecting close parent or element, but got just a string
$topArray[$key] .= "\n".$line;
}
else if (!empty($trim))
{
$result = $line;
}
}
$output = implode(n, $lines);
return $result;
}
/**
* @param string $output : The output of a multiple print_r calls, separated by newlines
* @return mixed[] : parseable elements of $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 is not allowed
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);
// 將類似 '[元素] => <換行> (' 的內容替換為 <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
函式 serialize_array(&$array, $root = '$root', $depth = 0)
{
$items = 陣列();
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 . ' = 陣列(';
$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] = another value
等等…
?>
對於需要在緩衝區回呼函數中印出陣列的人,我建立了這個快速函數。它只是將陣列作為可讀字串返回,而不是印出它。您甚至可以選擇以一般文字模式或 HTML 返回它。它是遞迴的,因此支援多維陣列。我希望有人覺得這很有用!
<?php
函式 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 = "陣列" . $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;
}
?>