При расширении DOMElement в PHP конструктор дочернего класса не вызывается. Ничто не выскочило из меня в документах, насколько это ожидалось, но, может быть, я что-то упустил. Вот простой тест ....Конструктор не вызвал расширенный PHP DOMElement
class SillyTestClass extends DOMElement{
public $foo=null;
public function __construct($name,$value=null,$namespace=null){
echo "calling custom construct....";
$this->foo="bar";
parent::__construct($name,$value,$namespace);
}
public function sayHello(){
echo "Why, hello there!";
}
}
$doc=new DOMDocument();
$doc->registerNodeClass('DOMElement','SillyTestClass');
$doc->loadHTML("<div><h1>Sample</h1></div>");
//THIS WORKS! CUSTOM CLASS BEING USED
$doc->documentElement->firstChild->sayHello();
//THIS IS STILL NULL:(Never set by construct, no message saying construct was called either
echo $doc->documentElement->firstChild->foo;
Конечно, если бы я его экземпляр сам это прекрасно ...
$elm=new SillyTestClass("foo","Hi there");
//WORKS! Outputs "bar";
echo $elm->foo;
Почему, когда я зарегистрировать класс узла с DOMDocument это не называют __construct
, хотя он дает мне надлежащее наследование любым другим способом?
UPDATE Для очень любопытных людей или людей, которые знают C
============================= ========================================= Расследование ....
Это является источником расширения DOM взяты из PHP src on github
Если вы должны были создать элемент, это цепь событий, которая происходит ::
document.c :: dom_document_create_element
| //uses libxml to generate a new DOMNode
| node = xmlNewDocNode(docp, NULL, (xmlChar *) name, (xmlChar *) value);
// that node is then sent to
php_dom.c :: php_dom_create_object
|
| //the node type is used to figure out what extension class to use
| switch (obj->type) {...
|
| //that class is used to instance an object
| if (domobj && domobj->document) {
| ce = dom_get_doc_classmap(domobj->document, ce);
| }
object_init_ex(return_value, ce);
Похоже, что вы не получите истинное наследство от простирающейся DOMNode или он встроен в классах расширений (DOMElement, DOMText), если экземпляры DomDocument им. В этом случае узел libxml создается первым, а свойства нашего класса привязаны вторым.
Это, к сожалению, невозможно обойти, потому что даже когда вы импортируетеNode в документ, он вводит новый узел. Пример
class extendsDE extends DOMElement{
public $constructWasCalled=false;
public function __construct($name){
parent::__construct($name);
$this->constructWasCalled=true;
}
}
class extendsDD extends DOMDocument{
public function __construct(){
parent::__construct();
$this->registerNodeClass("DOMElement","extendsDE");
}
//@override
public function createElement($name){
$elm=new extendsDE($name);
echo "Element construct called when we create=";
echo $elm->constructWasCalled?"true":"false";
return $this->importNode($elm);
}
}
$doc=new extendsDD();
$node=$doc->createElement("div");
echo "<br/>";
echo "But then when we import into document, a new element is created and construct called= ";
echo $node->constructWasCalled?"true":"false";
Теперь debate- это замыслом разработчиков и документация вводит в заблуждение, или это ошибка, и истинное наследство должно было иметь место?
В документации есть примечание, показывающее, что конструктор должен вызывать 'parent :: __ construct()'. Но я получаю тот же результат, что и вы. – Barmar
какую версию PHP вы использовали из любопытства? – user2782001
Я использовал PHP 5.5.38 – Barmar