Edit report at http://bugs.php.net/bug.php?id=52782&edit=1

 ID:                 52782
 Comment 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:             Open
 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:

(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


Previous Comments:
------------------------------------------------------------------------
[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

Reply via email to