在 PHP 中是否可以反向遍历一个 Traversable class 来找到根对象?
In PHP is it possible to reverse traverse a Traversable class to find the root object?
如果要扩展实现 Traversable 的内置 class,是否有可能使用 debug_backtrace?
获得对根对象的引用
例如,如果我有
$foo->bar->baz->biz->bon->bop->bob();
在 bop 的 bob 方法中我使用 debug_backtrace 有没有办法获得对 $foo 的引用? (那是什么?)
如果是这样,这是最优雅或最有效的方法吗?
我试过查看 debug_backtrace php.net 页面,但我仍然不清楚如何真正使用此功能,但从其他 material 和实验来看,我有疑问(查看更新)。
更新#1:
关于是否应该在生产代码中保留 debug_backtrace 似乎存在一些争论。 PHP debug_backtrace in production code to get information about calling method?
当然这部分是耦合问题,被调用对象应该知道调用它的对象吗?
更新#2
在找到 Find out which class called a method in another class 之后,我尝试使用我所学的知识来使用 debug_backtrace 进行反向遍历,但发现这不太可能。
<?php
class mother extends SimpleXMLElement {
protected $test_a = 'foo';
public $test_b = 'bar';
public function shout(){
echo "test_a '" , $this->test_a , "' while test_b '" , $this->test_b , "'.\n";
}
public function tell_mother($message,$limit=42){
$trace = debug_backtrace();
--$limit;
if($limit<1){
echo "Enough of that pointlessness\n";
var_dump($trace);
return 0;
}
if ( isset($trace[1]) && isset($trace[1]['object']) ){
// $trace[1] is the caller class
echo "I will pass the message on\n";
$trace[1]['object']->tell_mother($message,$limit);
}else{
echo "I am a " , get_class($this) , "\n";
echo "I have been told \"{$message}\".\n";
var_dump($trace);
}
}
}
echo "<pre>";
$xml = <<<XML
<?xml version='1.0'?>
<a>lob
<b>tob
<c>bob
<d>boo
<e>bin
<f>baz
<g>bar
<h>foo</h>
</g>
</f>
</e>
</d>
</c>
</b>
</a>
XML;
$obj = simplexml_load_string($xml,'mother');
$obj->b->c->d->e->f->g->h->tell_mother("I love her");
$obj->shout();
$obj->b->c->d->e->f->shout();
据我所知debug_backtrace 无法反向遍历并且无法访问对象范围内保存的值。
上面的输出给出
I am a mother
I have been told "I love her".
array(1) {
[0]=>
array(7) {
["file"]=>
string(58) "/home/[[snip]]_test.php"
["line"]=>
int(64)
["function"]=>
string(11) "tell_mother"
["class"]=>
string(6) "mother"
["object"]=>
object(mother)#2 (1) {
[0]=>
string(3) "foo"
}
["type"]=>
string(2) "->"
["args"]=>
array(1) {
[0]=>
&string(10) "I love her"
}
}
}
test_a '' while test_b ''.
test_a '' while test_b ''.
我的结论是内部 PHP 不认为子元素被父元素调用。所以我编辑了我的问题,简单地询问是否可以反向遍历 Traversable class。
通过问题中详细说明的跟踪和错误(主要是错误),我了解到至少有一些 PHP class 实现 Traversable 的似乎只是 classes但实际上是系统资源。
所以debug_backtrace(我的第一个想法)将无法反向遍历。这很可能是不可能的,但只要稍加巧妙,就可以创建一个委托包装器来提供对实际对象的两种遍历方式。
可以在我对另一个问题的回答中找到这样一个 class 的例子:
此外,debug_backtrace 不是在生产中执行任何超出其设计目的的错误记录和调试的好选择。
TD;DR:可能不会,但我们可以解决这个问题。
如果要扩展实现 Traversable 的内置 class,是否有可能使用 debug_backtrace?
获得对根对象的引用例如,如果我有
$foo->bar->baz->biz->bon->bop->bob();
在 bop 的 bob 方法中我使用 debug_backtrace 有没有办法获得对 $foo 的引用? (那是什么?)
如果是这样,这是最优雅或最有效的方法吗?
我试过查看 debug_backtrace php.net 页面,但我仍然不清楚如何真正使用此功能,但从其他 material 和实验来看,我有疑问(查看更新)。
更新#1:
关于是否应该在生产代码中保留 debug_backtrace 似乎存在一些争论。 PHP debug_backtrace in production code to get information about calling method?
当然这部分是耦合问题,被调用对象应该知道调用它的对象吗?
更新#2
在找到 Find out which class called a method in another class 之后,我尝试使用我所学的知识来使用 debug_backtrace 进行反向遍历,但发现这不太可能。
<?php
class mother extends SimpleXMLElement {
protected $test_a = 'foo';
public $test_b = 'bar';
public function shout(){
echo "test_a '" , $this->test_a , "' while test_b '" , $this->test_b , "'.\n";
}
public function tell_mother($message,$limit=42){
$trace = debug_backtrace();
--$limit;
if($limit<1){
echo "Enough of that pointlessness\n";
var_dump($trace);
return 0;
}
if ( isset($trace[1]) && isset($trace[1]['object']) ){
// $trace[1] is the caller class
echo "I will pass the message on\n";
$trace[1]['object']->tell_mother($message,$limit);
}else{
echo "I am a " , get_class($this) , "\n";
echo "I have been told \"{$message}\".\n";
var_dump($trace);
}
}
}
echo "<pre>";
$xml = <<<XML
<?xml version='1.0'?>
<a>lob
<b>tob
<c>bob
<d>boo
<e>bin
<f>baz
<g>bar
<h>foo</h>
</g>
</f>
</e>
</d>
</c>
</b>
</a>
XML;
$obj = simplexml_load_string($xml,'mother');
$obj->b->c->d->e->f->g->h->tell_mother("I love her");
$obj->shout();
$obj->b->c->d->e->f->shout();
据我所知debug_backtrace 无法反向遍历并且无法访问对象范围内保存的值。
上面的输出给出
I am a mother
I have been told "I love her".
array(1) {
[0]=>
array(7) {
["file"]=>
string(58) "/home/[[snip]]_test.php"
["line"]=>
int(64)
["function"]=>
string(11) "tell_mother"
["class"]=>
string(6) "mother"
["object"]=>
object(mother)#2 (1) {
[0]=>
string(3) "foo"
}
["type"]=>
string(2) "->"
["args"]=>
array(1) {
[0]=>
&string(10) "I love her"
}
}
}
test_a '' while test_b ''.
test_a '' while test_b ''.
我的结论是内部 PHP 不认为子元素被父元素调用。所以我编辑了我的问题,简单地询问是否可以反向遍历 Traversable class。
通过问题中详细说明的跟踪和错误(主要是错误),我了解到至少有一些 PHP class 实现 Traversable 的似乎只是 classes但实际上是系统资源。
所以debug_backtrace(我的第一个想法)将无法反向遍历。这很可能是不可能的,但只要稍加巧妙,就可以创建一个委托包装器来提供对实际对象的两种遍历方式。
可以在我对另一个问题的回答中找到这样一个 class 的例子:
此外,debug_backtrace 不是在生产中执行任何超出其设计目的的错误记录和调试的好选择。
TD;DR:可能不会,但我们可以解决这个问题。