扩展DOMElement [英] Extending 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
pre>
DOMElement
JavaScript
这里会发生什么?
如果我这样做:
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 aJavaScript
.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 aDOMElement
.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 withDOMDocument
, 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 aDOMElement
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 andJavaScriptLibrary
as subclass) and thenDOMDocument
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
DOMElement
s from the internal memory structure, you get it in the registered class, hereJavaScriptLibrary
.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屋!