使用其他 XML 源扩展 SimpleXML 类

对于当前的项目来说,如果能够扩展 SimpleXML 类来访问 SimpleXML 可遍历的魔力,那就太棒了。由于我无法理解的原因,构造函数是最终的。无论如何,我该如何延长课程呢?


到目前为止,我所做的是避免在子类上使用构造函数,而是创建一个静态方法来返回一个 XML 字符串,该字符串可在调用者中用于构造对象。不太漂亮,因为它给调用者带来了应该隐藏的模式的负担,但它正在起作用。是否有更优雅的方法来避免最终构造函数的阻碍设计选择?


namespace acme.com;

class SubXML extends \SimpleXML{

   static public createXML() {

        // here we return a magnificent XML string

        // probably from a DB or a REST interface

   }

}


$o = new \SubXML( \SubXML::createXML() );


达令说
浏览 82回答 1
1回答

呼啦一阵风

SimpleXMLElement 上的构造函数不仅仅是初始化 PHP 对象,而是调用外部库来初始化一些内部内存结构,然后在您遍历 XML 文档或片段时重用这些内部内存结构。扩展类的一种受支持的方法是将类的名称作为第二个参数传递给simplexml_load_string或simplexml_load_file,这将在您遍历时用于所有元素和属性。例如:class MyXML extends SimpleXMLElement {    public function hello() { echo "Hello ", $this->getName(); }}$sx = simplexml_load_string('<foo><bar><baz>42</baz></bar></foo>', 'MyXML');$sx->bar->baz->hello();目前尚不清楚如果MyXML在这种情况下有一个自定义构造函数会发生什么:是否应该为每个子元素调用它?有何论据?撇开这一点不谈,您的实际要求似乎是拥有某种工厂,它从某个来源(数据库、API)获取数据并创建某种对象。您的静态方法似乎是一个明智的方向,但可以直接返回对象而不是字符串:class SubXML extends SimpleXMLElement {   public static function createXMLfromDB($db) {        $xmlString = $db->query('Select XML from SpecialTable');        return simplexml_load_string($xmlString, static::class);   }}但是,我认为继承首先并不是表示这一点的特别好的方式 - 结果对象可能不需要知道其数据来自哪里,它需要能够表示该数据。因此,您的工厂可以是一个完全不同的类,以更适合测试的方式管理其依赖项:class MyXMLFromDBFactory {    private MyDBWrapper $db;    public function __construct(MyDBWrapper $db) {        $this->db = $db;    }    public function createXML() {        $xmlString = $db->query('Select XML from SpecialTable');        return simplexml_load_string($xmlString);    }}然后你可以有一个单独的MyXMLFromAPIFactory,MyXMLFromFileOnAmazonS3Factory等。如果你愿意,这些都可以返回相同的扩展SimpleXMLElement类,甚至可以将类名作为参数并将其传递给simplexml_load_string。
打开App,查看更多内容
随时随地看视频慕课网APP