【问题标题】:In PHP is it possible to reverse traverse a Traversable class to find the root object?在 PHP 中是否可以反向遍历 Traversable 类来查找根对象?
【发布时间】:2015-05-01 05:45:00
【问题描述】:

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

例如,如果我有

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

在 bob 的 bob 方法中我使用 debug_backtrace 有没有办法获得对 $foo 的引用? (那是什么?)

如果是这样,这是否是最优雅或最有效的方法?

我已经尝试查看 debug_backtrace php.net 页面,但我仍然不清楚如何真正使用此功能,但从其他材料和实验中我有疑问(请参阅更新)。

更新 #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 类。

【问题讨论】:

  • 在 bob 内部,那将是 $this ...不是吗?
  • Re: 不在生产环境中使用 - 我认为函数名的 debug 部分说明了一切。它是内存密集型的,并且应该只在您实现它来调试某些东西时使用。

标签: php oop design-patterns


【解决方案1】:

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

所以 debug_backtrace(我的第一个想法)将无法反转遍历。这很可能是不可能的,但只要稍加聪明,就可以创建一个委托包装器来提供对实际对象的两种遍历方式。

可以在我对我提出的另一个问题的回答中找到此类课程的示例:How do I obtain an iterative object reference to the root object in PHP?

此外,debug_backtrace 不是一个很好的选择,除了错误记录和调试之外的任何生产环境。

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

【讨论】:

  • Traversable 对象与您关于对象层次结构的问题和答案完全无关。 debug_backtrace 可能会起作用,但只能在您知道对象和嵌套对象如何实例化的受控设置中。 (debug_backtrace 处理调用堆栈)。对您的问题最常见的解决方案是在对象的构造函数中包含一个参数,该参数是对它的“父”对象的引用(或您的链接问题概述)
猜你喜欢
  • 1970-01-01
  • 2011-09-04
  • 1970-01-01
  • 2015-10-20
  • 1970-01-01
  • 1970-01-01
  • 2010-10-27
  • 2019-05-01
  • 1970-01-01
相关资源
最近更新 更多