Edit report at http://bugs.php.net/bug.php?id=52782&edit=1
ID: 52782 User updated by: bugs dot php dot net at moesen dot nu Reported by: bugs dot php dot net at moesen dot nu Summary: DOMDocument subclass forgotten using ->ownerDocument after closure Status: Bogus Type: Bug Package: DOM XML related Operating System: GNU/Linux 2.6.26-2-686 (Debian) PHP Version: 5.3SVN-2010-09-06 (snap) Block user comment: N New Comment: OK, thank you for the rationale. Contrary to the boilerplate text from the first paragraph, I did check the documentation. :-) I feel the documentation should be updated, because this paragraph is misleading: | When instantiating a custom DOMDocument the ownerDocument property | will refer to the instantiated class, meaning there is no need (and | in fact not possible) to use DOMDocument::registerNodeClass() with | DOMDocument This goes against your second advice quoted in the comment from 2010-10-07 09:32 UTC. For general reference, this is what I do in the function that creates the DOMDocument child instance and returns a DOMElement child of said document: $GLOBALS['XhtmlDocumentHack-' . uniqid()] = $document = new Xhtml10StrictDocument(); I have not checked if it is possible to override ->ownerDocument in the DOMElement child in order to keep a reference to the extended document alive. Previous Comments: ------------------------------------------------------------------------ [2010-10-19 19:36:40] rricha...@php.net Thank you for taking the time to write to us, but this is not a bug. Please double-check the documentation available at http://www.php.net/manual/ and the instructions on how to report a bug at http://bugs.php.net/how-to-report.php This is by design to minimize the system resource impact. The behavior you describe was the old behavior used in the domxml extension and purposely not duplicated. Objects wrapping the underlying XML tree live only as long as the user has a reference to them otherwise the only way to destroy any DOM object would be to de-reference every single object that wraps any portion on the underlying xml tree. ------------------------------------------------------------------------ [2010-10-07 11:32:14] bugs dot php dot net at moesen dot nu (Following up on e-mail correspondance with rrichards at php dot net.) > It'd most likely due to scoping. If you create an element based on a > subclass, it will only return the subclass as long as the element's > object (the DOM wrapper not the underlying XML structure) no longer > has any references. > > There are a couple ways to work around this: > > 1 - Always keep the doc object in global scope with at least 1 > reference to it. This really is only needed if you are attaching > custom data to any custom properties. This does indeed work around the problem, but I am not keen on polluting the global namespace. > 2 - The best way is to use: bool DOMDocument::registerNodeClass ( > string $baseclass , string $extendedclass ) > http://us2.php.net/manual/en/domdocument.registernodeclass.php Using > this mehod, you can register classes to always create specific node > types with rather than the default DOM classes so if you have any > custom methods they will always be available i.e. > > class myDoc extends DOMDocument { }; > > $doc = new myDoc(); > $doc->registerNodeClass("DOMDocument", "myDoc"); That works to a certain extent: the class is correct, but its custom properties are lost, as mentioned in work-around 1. The ownerDocument is an instance of MyDocument, but instead of being the original instance, it is a new instance (without calling the constructor) with all of its properties set to their defaults. It seems to me that as long as there is a DOMElement, there is an implicit reference to the original instance of the owner document (because of $domElement->ownerDocument), so said document should not be garbage collected. I have uploaded a simplified test case at http://codepad.org/CBsD3eVp ------------------------------------------------------------------------ [2010-09-20 13:19:34] bugs dot php dot net at moesen dot nu Is there anything I can do to get a confirmation on this? I tried #php on several networks, but they referred me to Freenode, where #php was full. ------------------------------------------------------------------------ [2010-09-06 15:43:15] bugs dot php dot net at moesen dot nu Err, my apologies for not cleaning up the path names. An oversight on my part. ------------------------------------------------------------------------ [2010-09-06 15:35:59] bugs dot php dot net at moesen dot nu Description: ------------ We have custom XML document and element classes that extend the original DOMDocument and DOMElement classes for convenience. There is a class that uses an instance of XmlElement obtained via a callback specified at construction time. That XmlElement works fine and stays that way. However, when we get its ownerDocument outside of the closure, the result is not an XmlDocument but a DOMDocument. I cannot see a single reason why. I tried several options, and it only seems to happen with that closure. I have checked versions 5.3.1, 5.3.2, 5.3.3 and now the latest 5.3.4 snapshot compiled with './configure && make'. Test script: --------------- http://codepad.org/hvrNh86K The original code uses a lot of namespaces and extends XmlDocument, but this is a much more minimal test case. Also try the "Uncomment this" code to see what /does/ work. Expected result: ---------------- *** Calling the callback directly... dom-fail.php:110: $container: XmlElement: <div id="content"/> dom-fail.php:111: $container->ownerDocument: XmlDocument; debug: object(XmlDocument)#2 (0) refcount(1){ } *** Calling callback from constructor()... dom-fail.php:110: $container: XmlElement: <div id="content"/> dom-fail.php:111: $container->ownerDocument: XmlDocument; debug: object(XmlDocument)#2 (0) refcount(1){ } *** In constructor, after check on $container: dom-fail.php:95: $container: XmlElement: <div id="content"/> dom-fail.php:96: $container->ownerDocument: XmlDocument; debug: object(XmlDocument)#2 (0) refcount(1){ } SUCCESS! Actual result: -------------- *** Calling the callback directly... dom-fail.php:110: $container: XmlElement: <div id="content"/> dom-fail.php:111: $container->ownerDocument: XmlDocument; debug: object(XmlDocument)#2 (0) refcount(1){ } *** Calling callback from constructor()... dom-fail.php:110: $container: XmlElement: <div id="content"/> dom-fail.php:111: $container->ownerDocument: XmlDocument; debug: object(XmlDocument)#2 (0) refcount(1){ } *** In constructor, after check on $container: dom-fail.php:95: $container: XmlElement: <div id="content"/> dom-fail.php:96: $container->ownerDocument: DOMDocument; debug: object(DOMDocument)#2 (0) refcount(1){ } PHP Fatal error: Call to undefined method DOMDocument::append() in /home/jmoe/fuckingpieceofshitfuckfuckfucksocks/dom-fail.php on line 100 ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/bug.php?id=52782&edit=1