VarDumper组件

3.4 版本
维护中的版本

VarDumper组件提供的是能够遍历任意PHP变量的架构。它基于dump()函数提供了更好的体验,你可以用它取代var_dump()

安装 

你可以通过下述两种方式安装:

然后,包容vendor/autoload.php文件,以开启Composer提供的自动加载机制。否则,你的程序将无法找到这个Symfony组件的类。

如果在Symfony框架内部使用此组件,确保DebugBundle在app/AppKernel.php文件中被开启。

dump()函数 

VarDumper组件创建了一个全局dump()函数供你取代var_dump()。使用本组件你可以得到:

  • 每个对象和资源类型(resource types)之专属视图层,如,在剥离一个单一proxy entity时过滤Doctrine内部的时候,或者,对开启的文件使用stream_get_meta_data函数进行深入洞察的时候(都可以使用dump());

  • 可配置的输出格式(output formats):HTML输出或命令行加亮输出;

  • 具备剥离内部引用的能力(Ability to dump internal references),不管是软引用(对象或资源)还是硬引用(对数组或对象属性施以=&)。相同对象/数组/资源的重复出现将不予二次显示乃至不再显示。更甚者,你能侦测你的数据的“引用结构”(reference structure);

  • 能够在一个“输出缓存控制器”(an output buffering handler)的上下文中(context)进行操作。

例如:

1
2
3
4
5
6
7
require __DIR__.'/vendor/autoload.php';
 
// create a variable, which could be anything!
// 创建一个变量,可以是任意内容!
$someVar = ...;
 
dump($someVar);

默认情况是,输出格式以及输出目标(destination)都是基于你当前的PHP SAPI而确定:

  • 对于命令行来说(CLI SAPI),输出是对STDOUT的写入。这给一些人带来惊喜,因为它绕过了PHP的输出缓存架构(output buffering mechanism);

  • 对于其他SAPIs,(对变量/资源等的)剥离(dumping)就是完成一个HTML常规输出。

如果你想把输出内容剥离成一个字符串,请阅读advanced documentation官方链接已失效文档,里面有例子。你可以学到如何改变(输出)格式,或者重定向输出内容到任何你希望的地方。

为了让dump()函数在你运行任何PHP代码时始终可用,你应该在电脑上进行全局安装:

  1. 运行composer global require symfony/var-dumper

  2. 添加auto_prepend_file = ${HOME}/.composer/vendor/autoload.php到你的php.ini文件中;

  3. 时常运行composer global update symfony/var-dumper以消除最新bug;

DebugBundle以及Twig的整合 

DebugBundle在Symfony完整版框架中被很好地整合进来。在Symfony标准版中,它被默认开启在devtest 环境。

由于在控制器中或是在程序的model层中生成(甚至debug)输出,有可能被发送HTTP头给阻断,或者破坏视图,本bundle配置了dump()函数,以便变量可以被剥离到web除错工具条中。

但如果工具条因为你调用die/exit而不被显示,或者有一个致命错误(fatal error)发生,那么这种(对变量的)剥离(dumping)将被写入常规输出(regular output)。

在Twig模板中,若要剥离一个变量,有两个函数可用。二选一的话应可满足大多数人的需求:

  • {% dump foo.bar %}的使用场合是,当原始模板输出不应被改变时:此时变量并不被行内剥离,而是在web除错工具条中;

  • 反过来说,{{ dump(foo.bar) }}进行的是行内剥离,也许并不适合于你的场合(比如你不应把它用在HTML属性中或是<script>之中)。

但这种行为可以被dump.dump_destination改变。有关于此的更多内容连同其他选项,请参考DebugBundle配置参考

在你的PHPUnit测试包里面使用VarDumper 

VarDumper组件提供了一个trait,可以帮你写一些PHPUnit的测试。

它提供两种新断言(assertions):

assertDumpEquals()

把被剥离的变量作为第二参数,来验证是否与提供在第一个参数中的预期的“字符串dump”相匹配。

assertDumpMatchesFormat()

与前面方法相类似,除了(第一个参数中的)预期的dump可以接收一个占位符,本方法基于PHPUnit提供的assertDumpStringMatchesFormat()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class ExampleTest extends \PHPUnit_Framework_TestCase
{
    use \Symfony\Component\VarDumper\Test\VarDumperTestTrait;
 
    public function testWithDumpEquals()
    {
        $testedVar = array(123, 'foo');
 
        $expectedDump = <<<EOTXT
array:2 [
  0 => 123
  1 => "foo"
]
EOTXT;
 
        $this->assertDumpEquals($expectedDump, $testedVar);
    }
}

Dump样例和输出 

对于简单变量,阅读输出信息是相当直白的。下面例子显示了一个定义在PHP中的变量被剥离之后的呈现:

1
2
3
4
5
6
7
8
$var = array(
    'a simple string' => "in an array of 5 elements",
    'a float' => 1.0,
    'an integer' => 1,
    'a boolean' => true,
    'an empty array' => array(),
);
dump($var);

灰色的箭头是一个切换按钮,用于隐藏/打开嵌套结构的子节点。

1
2
3
4
5
6
7
8
9
class PropertyExample
{
    public $publicProperty = 'The `+` prefix denotes public properties,';
    protected $protectedProperty = '`#` protected ones and `-` private ones.';
    private $privateProperty = 'Hovering a property shows a reminder.';
}
 
$var = new PropertyExample();
dump($var);

1
2
3
4
5
6
7
8
9
class PropertyExample
{
    public $publicProperty = 'The `+` prefix denotes public properties,';
    protected $protectedProperty = '`#` protected ones and `-` private ones.';
    private $privateProperty = 'Hovering a property shows a reminder.';
}
 
$var = new PropertyExample();
dump($var);

#14是内部对象操作的结果。它允许你比对相同对象的两次连续剥离的结果。

1
2
3
4
5
6
7
8
class DynamicPropertyExample
{
    public $declaredProperty = 'This property is declared in the class definition';
}
 
$var = new DynamicPropertyExample();
$var->undeclaredProperty = 'Runtime added dynamic properties have `"` around their name.';
dump($var);

1
2
3
4
5
6
7
class ReferenceExample
{
    public $info = "Circular and sibling references are displayed as `#number`.\nHovering them highlights all instances in the same dump.\n";
}
$var = new ReferenceExample();
$var->aCircularReference = $var;
dump($var);

1
2
3
4
5
6
7
8
$var = new \ErrorException(
    "For some objects, properties have special values\n"
    ."that are best represented as constants, like\n"
    ."`severity` below. Hovering displays the value (`2`).\n",
    0,
    E_WARNING
);
dump($var);

1
2
3
4
5
6
7
8
$var = array();
$var[0] = 1;
$var[1] =& $var[0];
$var[1] += 1;
$var[2] = array("Hard references (circular or sibling)");
$var[3] =& $var[2];
$var[3][] = "are dumped using `&number` prefixes.";
dump($var);

1
2
3
4
5
$var = new \ArrayObject();
$var[] = "Some resources and special objects like the current";
$var[] = "one are sometimes best represented using virtual";
$var[] = "properties that describe their internal state.";
dump($var);

1
2
3
4
5
6
7
8
$var = new AcmeController(
    "When a dump goes over its maximum items limit,\n"
    ."or when some special objects are encountered,\n"
    ."children can be replaced by an ellipsis and\n"
    ."optionally followed by a number that says how\n"
    ."many have been removed; `9` in this case.\n"
);
dump($var);

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)