如何将var_dump的结果捕获到一个字符串中?

677
我想将var_dump的输出捕获到一个字符串中。
PHP文档中说:
引用: 与任何直接将结果输出到浏览器的内容一样,可以使用输出控制函数来捕获此函数的输出,并将其保存在一个字符串中(例如)。
那么,这可能是如何工作的一个例子呢? print_r()不是一个有效的选择,因为它不能给我所需的信息。

2
我知道时间有点过去了,但我在问题中读到了这句话:“不会给我我需要的信息”。因此,在问题中添加你需要的信息可能会很有用。 - Valerio Bozz
13个回答

963

试一下var_export

你可能想要尝试一下var_export - 它虽然不能像var_dump一样提供相同的输出,但它提供了一个第二个$return参数,这将导致它返回其输出而不是打印出来:

$debug = var_export($my_var, true);

为什么要这样做?

相比于使用 ob_startob_get_clean(),我更喜欢这个简短的代码。同时我发现输出结果更容易阅读,因为它只是 PHP 代码。

var_dumpvar_export 的区别在于,var_export 返回一个"可解析的变量字符串表示",而 var_dump 仅仅是将有关变量的信息打印出来。在实际应用中,这意味着 var_export 可以给你有效的 PHP 代码(但可能不会提供足够多的关于变量的信息,特别是当你处理资源类型时)。

演示:

$demo = array(
    "bool" => false,
    "int" => 1,
    "float" => 3.14,
    "string" => "hello world",
    "array" => array(),
    "object" => new stdClass(),
    "resource" => tmpfile(),
    "null" => null,
);

// var_export -- nice, one-liner
$debug_export = var_export($demo, true);

// var_dump
ob_start();
var_dump($demo);
$debug_dump = ob_get_clean();

// print_r -- included for completeness, though not recommended
$debug_printr = print_r($demo, true);

输出的差异:

var_export(在上面的示例中,$debug_export):

 array (
  'bool' => false,
  'int' => 1,
  'float' => 3.1400000000000001,
  'string' => 'hello world',
  'array' => 
  array (
  ),
  'object' => 
  stdClass::__set_state(array(
  )),
  'resource' => NULL, // Note that this resource pointer is now NULL
  'null' => NULL,
)

var_dump ($debug_dump在上面的示例中):

 array(8) {
  ["bool"]=>
  bool(false)
  ["int"]=>
  int(1)
  ["float"]=>
  float(3.14)
  ["string"]=>
  string(11) "hello world"
  ["array"]=>
  array(0) {
  }
  ["object"]=>
  object(stdClass)#1 (0) {
  }
  ["resource"]=>
  resource(4) of type (stream)
  ["null"]=>
  NULL
}

打印上面示例中的 $debug_printr:

Array
(
    [bool] => 
    [int] => 1
    [float] => 3.14
    [string] => hello world
    [array] => Array
        (
        )

    [object] => stdClass Object
        (
        )

    [resource] => Resource id #4
    [null] => 
)

注意事项:var_export不能处理循环引用

如果你试图转储一个存在循环引用的变量,调用var_export会导致PHP发出警告:

 $circular = array();
 $circular['self'] =& $circular;
 var_export($circular);

结果为:

 Warning: var_export does not handle circular references in example.php on line 3
 array (
   'self' => 
   array (
     'self' => NULL,
   ),
 )

另一方面,var_dumpprint_r 遇到循环引用时会输出字符串 *RECURSION*


11
这个回答肯定比被采纳的那个更好。我很惊讶它没有更多的赞!您能否详细说明为什么它可能不提供他正在寻找的所有信息? - JMTyler
7
var_export 返回一个可解析的字符串,本质上是 PHP 代码,而 var_dump 则提供数据的原始转储。例如,如果你对值为1的整数调用 var_dump,则它会打印 int(1),而 var_export 只会打印出 1 - inxilpro
4
如果在使用$GLOBALS时使用var_export,它会输出无内容,而var_dump则不会有这个问题。 - Olaf
4
不能使用包含对自身的引用的变量。var_export不能像var_dump那样工作;例如,$v=[];$v[]=&$v;var_export($v,true); - hanshenrik
4
不要夸大其词。var_export 并不是更好的调试工具,因为你无法在浏览器中搜索 (int)(string) 等内容。它还会把大量信息混杂在一个小空间内,你可以试试这个命令:var_export(''); var_export('\'');。最重要的是,准备好迎接致命错误:*PHP Fatal error: Nesting level too deep - recursive dependency? in C:\path\file.php on line 75* - Pacerier
显示剩余4条评论

653

使用输出缓冲:

<?php
ob_start();
var_dump($someVar);
$result = ob_get_clean();
?>

9
在这里使用输出缓冲很可能会对性能产生负面影响。在执行复杂脚本期间,如果需要查看多个变量,则可能会变得非常混乱。请注意保持原意并尽可能地通俗易懂。 - selfawaresoup
87
我只是把 var_dump 作为调试的一种便利功能来使用,并且肯定从未在产品代码中保留 var_dump 语句。我想这是很典型的情况。在这种情况下,性能不太可能有任何影响。 - Mark Amery
12
这是对问题的很好的字面回答,因为您完全像被问到的那样“将var_dump的结果捕获到字符串中”。 var_export()从本质上讲是更好的答案,因为它通常更有意义。 - Josh from Qaribou
2
@AlbertHendriks 我更喜欢使用 var_dump。启用 Xdebug 后,您可以获得漂亮的数据显示。 - robsch
2
这是完美的答案。var_export的答案冗长而无关紧要,因为它既不使用var_dump也不使用输出捕获,并且var_exportprint_r一样都不提供类型信息。 - webb
显示剩余3条评论

85

你也可以这样做:

$dump = print_r($variable, true);

18
我确实提到了 var_dump :) - Mark Biek
8
我个人更喜欢在可以的情况下使用print_r,但不幸的是有时它无法提供足够的信息。例如,由于它会在可能的情况下转换为字符串,因此falsenull都显示为空字符串。在我关心它们之间区别的情况下,我会勉强使用var_dumpvar_export - JMTyler

22

如果您使用的是 PHP > = 7.0.0

function return_var_dump(...$args): string
{
    ob_start();
    try {
        var_dump(...$args);
        return ob_get_clean();
    } catch (\Throwable $ex) {
        // PHP8 ArgumentCountError for 0 arguments, probably..
        // in php<8 this was just a warning
        ob_end_clean();
        throw $ex;
    }
}

或者如果您正在使用的是 PHP >=5.3.0:

function return_var_dump(){
    ob_start();
    call_user_func_array('var_dump', func_get_args());
    return ob_get_clean();
}

或者如果您使用的是PHP<5.3.0(这个函数实际上向后兼容到PHP4)


function return_var_dump(){
    $args = func_get_args(); // For <5.3.0 support ...
    ob_start();
    call_user_func_array('var_dump', $args);
    return ob_get_clean();
}

在5.3.0版本之前,如果直接将func_get_args用作另一个函数调用的参数,会存在一个bug,因此您必须将其放入变量中并使用该变量,而不是直接将其用作参数。


4
@MarkAmery 似乎是真的。我只是让它更容易理解了。 - hanshenrik
PHP5.6+ function vardump(...$args){if(count($args)){ob_start();var_dump(...$args);return ob_get_clean();}return '';}PHP5.6+ function vardump(...$args){if(count($args)){ob_start();var_dump(...$args);return ob_get_clean();}return '';} - a55
@a55 更像是这样的 function vardump(...$args){if(count($args)){ob_start();var_dump(...$args);return ob_get_clean();}else{trigger_error("vardump() 至少需要一个参数,但没有给出。",E_USER_ERROR);return "";}} - 对于 PHP<8,当您给 var_dump() 0 个参数时,它会触发一个错误,因此当没有参数时,您的 vardump 应该做同样的事情。但如果您使用的是 PHP>=8,则会抛出 ArgumentCountError 异常,因此您的 vardump() 在 php>=8 中也应该做同样的事情。 - hanshenrik

16

另外,echo json_encode($dataobject); 可能会有所帮助。


1
在这种情况下,我的看法是输出非常混乱,远离调试目的。 - Tomáš Zato
2
Mark Biek没有提到调试,是吗?也许他只需要将对象保存在数据库中。在这种情况下,我的提供的方法会很好用。无论如何,感谢你的提醒,Tomáš Zato。 - ZurabWeb
无论如何,json_encode 不会包含 var_dump 所有的数据(例如变量类型)。json_encode 输出与 print_R 相同的信息,只是格式不同。 - Tomáš Zato
2
好的,我会再解释一遍。OT 表示他需要 var_dump 的输出结果。他还表示 print_R 提供的信息不足以满足他的需求。json_encodeprint_r 提供的信息没有实质性的区别,只是数据格式不同。鉴于此,如果 print_r 不够用,那么 json_encode 也是如此。请不要再抱怨关于投票的事情了。显然这不是随意点击,所以请接受它。 - Tomáš Zato

15

您也可以尝试使用serialize()函数,有时它对于调试非常有用。


7
警告一句 - 如果您希望将输出作为字符串进行error_log,则不应使用此解决方案,因为serialize的输出可能包含空字节,而error_log会截断包含空字节的字符串。 - Mark Amery

12

PHP手册中提到:

此函数显示有关一个或多个表达式的结构化信息,包括其类型和值。

因此,这里是PHP的var_dump()真正返回版本,实际上接受可变长度的参数列表:

function var_dump_str()
{
    $argc = func_num_args();
    $argv = func_get_args();

    if ($argc > 0) {
        ob_start();
        call_user_func_array('var_dump', $argv);
        $result = ob_get_contents();
        ob_end_clean();
        return $result;
    }

    return '';
}

3
只回答实际问题并提供真正答案的用户会得到加一分。我正在阅读这篇内容,因为我需要var_dump,而不是var_export、print_r、serialize、json_encode或一个真正的调试器。我也知道如何使用它们。OP要求var_dump,我需要var_dump,谢谢! - Slashback
如果你想保持 var_dump 的真实性,当 argc<=0 时,你必须触发错误信息 "Wrong parameter count for var_dump_str()";或者更好的方法是让 var_dump 自动处理。 :p - hanshenrik
1
这几乎没有添加任何已经在被接受的答案中提到的内容。这里的 $argc 检查是不必要的,而且可以说是错误的,正如 @hanshenrik 指出的那样,一旦你去掉它,你真正添加的只是 call_user_func_arrayfunc_get_args 调用。 - Mark Amery

5

如果您想在运行时查看变量的内容,考虑使用真正的调试器,例如XDebug。这样您就不需要破坏源代码,并且即使在普通用户访问您的应用程序时,您也可以使用调试器。他们不会注意到。


5

以下是完整的函数解决方案:

function varDumpToString ($var)
{
    ob_start();
    var_dump($var);
    return ob_get_clean();
}

2
无法处理超过1个变量...var_dump("foo","bar") => string(3) "foo" string(3) "bar" varDumpToString("foo","bar") => string(3) "foo" - hanshenrik

2

这可能有些跑题。

我正在寻找一种方法,将这种信息写入我的PHP-FPM容器的Docker日志,并想出了下面的片段。我相信这可以被Docker PHP-FPM用户使用。

fwrite(fopen('php://stdout', 'w'), var_export($object, true));

1
然而,该句柄从未关闭,因此存在资源泄漏的问题,这可能会在长时间运行的守护进程式脚本中成为问题。但是尝试使用 file_put_contents('php://stdout',var_export($object, true),FILE_APPEND); - hanshenrik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接