PHP - 我可以获取对象而不是方法返回吗?

时间:2015-01-17 00:50:18

标签: php domdocument php-5.5

我想说我想将一个div附加到DOMDocument。我可以这样做:

<?php
$dom = new DOMDocument();

$dom->appendChild(
    $dom->createElement("div")
);

现在,说我想在该div中添加一些文字,所以我尝试:

<?php
$dom = new DOMDocument();

$dom->appendChild(
    $dom->createElement("div")
        ->appendChild( $dom->createTextNode("foobar") )
);

但是等等!现在有一个问题!

在第一种情况下,$dom->createElement("div")返回一个空的&#34; div&#34; DOMNode,appendChild()接受没有问题。

但在第二种情况下,$dom->createElement("div")->appendChild($dom->createTextNode("foobar"))会返回已经附加的&#34; foobar&#34;一个DOMText。所以&#34; div&#34; DOMNode没有被追加,并且php会发出警告。

Warning: DOMNode::appendChild(): Couldn't fetch DOMText

我的问题是,有没有办法让方法链返回原始修改的(附加了DOMText)DOMEode,由createElement()返回?

我知道我可以将DOMNode保存到变量然后将其传递给appendChild(),但我真的很想看到一个单线解决方案。

感谢。

小提琴:http://codepad.org/PFB3Ns7E

2 个答案:

答案 0 :(得分:1)

如果您使用PHP 5.6+,则可以使用spread / splat运算符(...)与魔术方法__call结合使用来修补类以满足您的需求。

基本上,您创建两个模仿DOMDocumentDOMNode行为的代理类,称为DOMDocumentPlusDOMNodePlus。每个班级都包含一个指向真实班级的私人链接,并且通过使用魔术方法__call,我们可以将几乎所有调用委托给原始班级&#39;方法。然后,当您在appendChild元素上调用DOMNodePlus时,您将返回$this而不是孩子。

DOMDocumentPlus课程

class DOMDocumentPlus {

    private $dom;

    public function __construct(...$args) {
        $this->dom = new DOMDocument(...$args);
    }

    public function __call($name, $args) {
        if($name !== 'createElement') {
            return $this->dom->$name(...$args);
        } else {
            return new DOMNodePlus($this->dom->createElement(...$args));
        }
    }   

}

DOMNodePlus课程

class DOMNodePlus {

    private $node;

    public function __construct($node) {
        $this->node = $node;
    }

    public function __call($name, $args) {
        if($name !== 'appendChild') {
            return $this->node->$name(...$args);
        } else {
            $this->node->appendChild(...$args);
            return $this->node;
        }
    }

}

主程序

$dom = new DOMDocumentPlus();

$dom->appendChild(
    $dom->createElement("div")->appendChild($dom->createTextNode("foobar"))
);

$dom->formatOutput = true;
echo $dom->saveHTML();

答案 1 :(得分:1)

是的,首先附加div

$dom = new DOMDocument();

$dom
  ->appendChild(
    $dom->createElement("div")
  )
  ->appendChild( 
     $dom->createTextNode("foobar") 
  );

echo $dom->saveXml();

输出:

<?xml version="1.0"?>
<div>foobar</div>

您可以使用$parentNode属性再次向上移动。

$dom = new DOMDocument();

$dom
  ->appendChild(
    $dom->createElement("div")
  )
  ->appendChild( 
     $dom->createTextNode("foobar") 
  )
  ->parentNode
  ->appendChild(
     $dom->createElement("span")
  )
  ->appendChild( 
     $dom->createTextNode("FOOBAR") 
  );

echo $dom->saveXml();

输出:

<?xml version="1.0"?>
<div>foobar<span>FOOBAR</span></div>

但不要过度使用它。像这样的长链不易维护。