因此,我们可能会
<?PHP $MyPage = new XPage($HTML);
到现在为止还挺好.我现在需要做的是选择XML文档的某些部分,以便它们可以“加入书签”(我确信它有一个更好的名称)所以你可以这样做
$MyPage->ThatBit("foo")->addChild('p',$MyParagraph);
理想情况下,我希望能够去
$MyPage->page()->body->header->RememberThisBitAs("foo");
或者直观相似的东西.然后应该发生的是对象$MyPage(XPage类型)应该传递参考,在这种情况下是html / body / header(这可能不是正确的XPath表示法,但希望你可以遵循).
这个想法是最常见的访问区域可以更顺利地获得.这就是SimpleXML类(即使使用我的扩展名)遇到的东西,如果没有另一个工厂,它也无法做到,并使XPage成为单例.
然而,XPage类($MyPage)包含“书签”数组.据我所知,没有办法在SimpleXML的迭代中传递引用,以便孩子或孩子的孩子不能告诉工厂“请我加书签”.
这会让我做一些讨厌的事情:
$MyPage->addBookmark("foo",$MyPage->page()->body->header->getChildren() );
这似乎不对.
要么
$MyPage->page()->body->header->RememberThisBitAs("foo",$MyPage);
这不是那么糟糕,但仍然“感觉”错了.
如何在没有过多的对象耦合或丑陋的自我引用的情况下处理此问题?
更新
我想知道是否可以使用debug_backtrace反转遍历一个类,但答案似乎是否定的.
In PHP is it possible to reverse traverse a Traversable class to find the root object?
其他类似的测试表明,在可遍历堆栈中的任何其他元素上都无法访问在元素上设置类变量的值.
我将专注于包装器的建议.
更新
SimpleXML实际上不是真正的对象,而是系统资源.这可以解释我的痛苦来自哪里.说说明:http://php.net/manual/en/class.simplexmlelement.php
因此,对于所有对象感觉就像一串对象相互调用,实际上并非如此.
您可以修改XPage类的方法以返回XPage对象而不是simpleXMLElements(或另一个扩展simpleXMLElement的类).然后,该类可以具有包含对“root”元素的引用的附加属性.
所以基本上你的“包装类”看起来像这样(前面的伪代码!):
class Wrap extends simpleXMLElement { private $root = null; private $refs = array(); public function addReference($name,$element = null) { if($element === null) { $element = $this; } if($this->root === null) { $this->refs[$name] = $this; } else { $this->root->addReference($name,$this); } } public function getReference($name) { if($this->root === null) { return $this->refs[$name]; } else { return $this->root->getReference($name); } } }
所以你上面的用例看起来像这样:
$MyPage->page()->body->header->addReference("foo"); $MyPage->getReference("foo")->addChild('p',$MyParagraph);
选项2:添加ID
$MyPage->page()->body->header->addAttribute("id","foo"); $MyPage->xpath("//*[@id='foo']")->addChild('p',$MyParagraph);