在PHP中,可以反向遍历Traversable类来查找根对象


In PHP is it possible to reverse traverse a Traversable class to find the root object?

如果要扩展实现Traversable的内置类,是否可以通过debug_backtrace获得对根对象的引用?

例如,如果我有

$foo->bar->baz->biz->bon->bop->bob();

在bop的bob方法中,我使用debug_backtrace,有没有一种方法可以获得对$foo的引用?(那是怎么回事?)

如果是的话,这是最优雅或最有效的方法吗?

我试过查看debug_backtrace php.net页面,但我仍然不清楚如何真正使用这个函数,但从其他材料和实验来看,我有疑问(请参阅更新)。

更新#1:

关于是否应该在生产代码中保留debug_backtrace,似乎确实存在一些争论。在生产代码中使用PHP debug_backtrace来获取有关调用方法的信息?

当然,这其中的一部分是耦合问题,被调用的对象应该知道调用它的对象吗?

更新#2

在找到在另一个类中调用方法的类后,我尝试使用我所学到的使用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类。

通过问题中详细介绍的跟踪和错误(主要是错误),我了解到至少一些实现Traversable的PHP类看起来只是类,但实际上是系统资源。

所以debug_backtrace(我的第一个想法)将无法反转遍历。这可能是不可能的,但只要有一点独创性,就可以创建一个委托包装器来提供实际对象的双向遍历。

在我对另一个问题的回答中可以找到这样一个类的例子:如何在PHP中获得对根对象的迭代对象引用?

此外,debug_backtrace并不是在生产中进行任何事情的好选择,除了错误日志记录和调试之外。

TD;DR:可能不会,但我们可以解决。