扩展DOMElement [英] Extending DOMElement

查看:99
本文介绍了扩展DOMElement的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个奇怪的行为扩展PHP DOMElements:

 类JavaScript扩展DOMElement {
}

class JavaScriptLibrary扩展DOMElement {
}

$ dom = new DOMDocument();

$ node = new JavaScript('script');
$ dom-> appendChild($ node);

$ node = new JavaScriptLibrary('script');
$ dom-> appendChild($ node);

$ node = new JavaScript('script');
$ dom-> appendChild($ node);

foreach($ dom-> childNodes as $ childNode){
echo get_class($ childNode)。\\\
;
}

预期:

  JavaScript 
JavaScriptLibrary
JavaScript

结果:

  DOMElement 
DOMElement
JavaScript
pre>

这里会发生什么?



如果我这样做:

  addElement($ dom,new JavaScript('script')); 
addElement($ dom,new JavaScriptLibrary('script'));
addElement($ dom,new JavaScript('script'));

函数addElement($ dom,$ node){
$ dom-> appendChild($ node);
}

结果将是

  DOMElement 
DOMElement
DOMElement

如何在不使用 - > createElement的情况下执行此操作,如我如何扩展PHP DOMElement?

解决方案

首先,您可能会想知道在第一个例子中会发生什么。为什么(地狱))是前两个,一个 DOMElement ,第三个是 JavaScript



这是因为$ code> $ node 变量尚未重新分配或未设置。如果您未设置或重新分配,则输出不同:

  $ node = 1; #re-assing to(int)1 

foreach($ dom-> childNodes as $ childNode){
echo get_class($ childNode)\\\
;
}

输出:

  DOMElement 
DOMElement
DOMElement

正如你所看到的,现在第三个就像前两个。



这可能已经给你一个指针。只要你的 DOMNode 对象保存在PHP变量内存中,就是你的类型。当没有,你从父元素或文档(没有它在你的某个变量)中读取它时,它从其他内存中读取,并将作为一个 DOMElement



这意味着PHP不会在内存中保留多个 DOMElement 只是因为文档有很多元素,而且内部还有一些其他数据结构,当您与 DOMDocument 进行交互时,PHP将即时创建这些对象(除非对象已经创建,仍然在变量内存中。)



所以这应该解释为什么前两个是 DOMElement $ node 被重新分配,所以它们不再在PHP变量内存中),而对于第三个节点,它仍然在内存中,因此没有创建



有了这个解释,现在还应该更清楚哪些限制:即使你添加了更具体的 DOMElement 节点去做(例如) JavaScript JavaScriptLibrary )它不能意味着你从DOM获取它。因为DOM只是一个模型,它保证给你一个 DOMElement 而不是你在那里填充。



我刚刚谈到的内存中的这个结构,没有PHP对象存在但仍然表示所有元素,是基于一个名为libxml的库。 PHP使用这些。



所以每次PHP根据这些内部结构为$ code> DOMElement 创建一个新对象时,它使用相同名称PHP类。



您可以通过注册基类的子类(例如 DOMDocument 作为基类和 JavaScriptLibrary 作为子类),然后 DOMDocument 将创建一个新的对象实例 - 使用所以不需要在上面的例子变体中重新分配给 $ node ,所以我们注册了一个不同的类:

  $ dom-> registerNodeClass('DOMElement','JavaScriptLibrary'); 

foreach($ dom-> childNodes as $ childNode){
echo get_class($ childNode)。\\\
;
}

输出:

  JavaScriptLibrary 
JavaScriptLibrary
JavaScript

Etvoilà!只要PHP从内部存储器结构中创建了这些 DOMElement s ,就可以在注册的类中找到它,这里 JavaScriptLibrary



如果这仍然是有限的,你想做什么,我知道处理这个的唯一方法是延长 DOMDocument ,在构造时自引用它(所以这个对象不会丢失),子类别任何其他节点类型对于任何添加,请保留您在内存中添加的对象,以便它像第三个一样返回按原样。



如果你想为了开发这个快速,我建议你使用一个名为traits的PHP 5.4功能,即使大多数这些domdocument扩展类从 DOMNode 扩展,你不能为自己子类,他们需要从他们的基类扩展,否则这将不起作用。由于PHP没有多重继承,所以traits可以帮助您在实例/对象管理中创建的所有许多子类之间不重复写入代码。



还有一些关于 DOMDocument -Model的知识,以便您了解如何添加和删除节点,以便您可以管理内存。我不能说如果这是值得的工作,甚至100%可能的你尝试做的。


I got a strange behaviour extending PHP DOMElements:

class JavaScript extends DOMElement {
}

class JavaScriptLibrary extends DOMElement {
}

$dom = new DOMDocument();

$node = new JavaScript('script');
$dom->appendChild($node);

$node = new JavaScriptLibrary('script');
$dom->appendChild($node);

$node = new JavaScript('script');
$dom->appendChild($node);

foreach ($dom->childNodes as $childNode) {
    echo get_class($childNode)."\n";
}

Expected:

JavaScript
JavaScriptLibrary
JavaScript

Result:

DOMElement
DOMElement
JavaScript

What will be happend here?

If I do it this way:

addElement($dom, new JavaScript('script'));
addElement($dom, new JavaScriptLibrary('script'));
addElement($dom, new JavaScript('script'));

function addElement($dom, $node){
    $dom->appendChild($node);
}

The result will be

DOMElement
DOMElement
DOMElement

How can I do this without using ->createElement like here "How can I extend PHP DOMElement?".

解决方案

First of all you might wonder what happens here in your first example. Why (the hell ;)) are the first two ones a DOMElement and the third one a JavaScript.

That is because the $node variable has not been re-assigned or unset so far. If you unset or re-assign it, the output differs:

$node = 1; # re-assing to (int) 1

foreach ($dom->childNodes as $childNode) {
    echo get_class($childNode)."\n";
}

Output:

DOMElement
DOMElement
DOMElement

As you can see, the third one now is like the first two ones.

This might already give you a pointer. As long as your DOMNode object is kept in PHP variable-memory, it is of your type. When not and you read it "back" from the parent element or the document (without having it in some variable of yours), it is read from some other memory and returned as a DOMElement.

That means, PHP does not keep numerous DOMElement objects in memory only because the document has that many elements but internally there is some other data-structure and when you interact with DOMDocument, PHP will create these objects on-the-fly (unless that object was already created and still is in variable-memory).

So this should explain why the first two were DOMElement ($node was re-assigned so they were not in PHP-variable-memory any longer) while for the third node, it still was in memory and therefore was not created.

With this explanation, it should also now be more clear where the limitation is: Even though you add a more specific DOMElement node to the document (e.g. JavaScript, JavaScriptLibrary) it must not mean that you get it back from the DOM. Because the DOM only is a model that guarantees giving you back a DOMElement and not "what you stuffed in there".

This structure in memory I've just talked about, where no PHP objects exist but still all elements are represented, is based on a library called libxml. PHP makes use of the these.

So each time PHP creates a new object based on these internal structure for a DOMElement it uses the same-named PHP class.

You can change the class-name here BTW by registering a subclass of a base-class (e.g. DOMDocument as base-class and JavaScriptLibrary as subclass) and then DOMDocument will - when creating a new object instances - use that class instead.

So instead of re-assigning to $node in the example-variation above, we register a different class:

$dom->registerNodeClass('DOMElement', 'JavaScriptLibrary');

foreach ($dom->childNodes as $childNode) {
    echo get_class($childNode)."\n";
}

Output:

JavaScriptLibrary
JavaScriptLibrary
JavaScript

Et voilà!; as long as PHP creates those DOMElements from the internal memory structure, you get it in the registered class, here JavaScriptLibrary.

If this still is too limited for what you want to do, the only way I know of to deal with this is to extend DOMDocument, self-reference it when constructed (so this object does not get lost), subclass any other node-type, for any adding, keep the object you've added in memory so that it does return "as-is" like you experienced with the third one.

If you want to develop that fast, I suggest you make use of a PHP 5.4 feature called traits as even most of those domdocument-extension-classes extend from DOMNode, you can not for your own sub-classes, they need to extend from their base-class otherwise this won't work. As PHP does not have multiple inheritance, traits can help here to not duplicate write code between all the many sub-classes you will need to create for your instance/object management.

Also good knowledge about the DOMDocument-Model is recommended so that you understand how nodes are added and removed so that you can manage the memory. I can not say if it's worth the work or even 100% possible for what you try to do.

这篇关于扩展DOMElement的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆