ID: 35104
User updated by: php at tjworld dot net
Reported By: php at tjworld dot net
Status: Assigned
Bug Type: Class/Object related
Operating System: Windows 2003
PHP Version: 5.1.0RC5
Assigned To: dmitry
New Comment:
"but DOM properties CANNOT be overriden."
Does this occur anywhere else in the PHP classes or is it unique to
DOM? It's the first time I've met this situation in OO since the 80's.
It pretty much makes having the DOM object-oriented pointless, when the
base class (DOMNode) of the other significant DOM classes prevents
useful extension.
A simple solution would be to provide a courtesy:
DOMNode->__construct($ownerDocument = null);
But that'd be available to the public of course. Alternatively,
protected DOMNode function _setOwnerDocument(DOMDocument
ownerDocument);
But thats a bit arbitary. Alternatively, solve the practical loss of
functionality by fixing the bug in importNode() so it returns an object
of the class passed in:
DOMNode DOMDocument->importNode(DOMNode $node, bool deep);
Currently it *casts* the passed $node to one of the DOM base classes it
inherited from *and* discards all their extended properties and methods,
which is surely not OO behaviour because in the following scenario, the
cases listed at the end are inconsistent:
class inChild extends DOMNode {}
class inGrandChild extends DOMElement()
class inGreatGrandChild extends inGrandChild()
$node = new DOMNode();
$element = new DOMElement();
$child = new inChild();
$grandChild = new inGrandChild();
$greatGrandChild = new inGreatGrandChild();
1. DOMDocument->importNode($node, true) instanceof DOMNode
2. DOMDocument->importNode($element, true) instanceof DOMElement
3. DOMDocument->importNode($child, true) instance of DOMNode
4. DOMDocument->importNode($grandChild, true) instanceof DOMElement
(not inGrandChild)
5. DOMDocument->importNode($greatGrandChild, true) instanceof
DOMElement (not inGreatGrandChild)
So importNode() doesn't even cast to a consistent DOMNode, but to the
'highest* level in the built-in classes.
Usually in OO although the cast is to a super-class (to guarantee
portability) the extended methods and properties aren't discarded.
If importNode() were fixed to return the same class as passed in the
following code would solve the ownerDocument issue:
<?php
class extDOMDocument extends DOMDocument {
public function createElement($name, $value=null) {
$orphan = new extDOMElement($name, $value);
$adopt = $this->importNode($ret, true); // adopt it
// now $adopt satisfies $this->isSameNode($adopt->ownerDocument) &&
$adopt instanceof extDOMelement
return $adopt;
}
}
class extDOMElement extends DOMElement {
function __construct($name, $value=null, $namespace=null) {
parent::__construct($name, $value, $namespaceURI);
}
// ... more class definition here
}
(excuse any typo's - working weird hours!)
Previous Comments:
------------------------------------------------------------------------
[2005-11-04 17:02:40] [EMAIL PROTECTED]
I can't speak for the user class example, but DOM properties CANNOT be
overriden.
------------------------------------------------------------------------
[2005-11-04 16:26:34] [EMAIL PROTECTED]
Dmitry, any insight on this?
------------------------------------------------------------------------
[2005-11-04 13:27:28] php at tjworld dot net
Further test using DOMDocument/DOMElement...
C:\PHP\5.1.0RC5-dev>php.exe dom.php
Fatal error: extDOMElement::__construct(): Cannot write property in
C:\dom.php on line 14
----------dom.php-------------
<?php
class extDOMDocument extends DOMDocument {
public function createElement($name, $value=null) {
$ret = new extDOMElement($name, $value, $this); // create the new
element with this Document as owner
return $ret;
}
}
class extDOMElement extends DOMElement {
function __construct($name, $value='', $owner=null,
$namespaceURI=null) {
if(!$owner instanceof extDOMDocument)
throw new DOMException(DOM_NOT_FOUND_ERR); // illegal owner
parent::__construct($name, $value, $namespaceURI);
$this->ownerDocument = $owner; //** this line causes a Fatal Error
}
// ... more class definition here
}
$doc = new extDOMDocument('test');
$el = $doc->createElement('tagname');
?>
------------------------------------------------------------------------
[2005-11-04 13:02:41] php at tjworld dot net
C:\PHP\5.1.0RC5-dev>php.exe test.php
testing...
Fatal error: Uncaught exception 'Exception' with message 'Can't
overwrite test' in C:\test.php:12
Stack trace:
#0 C:\test.php(23): ReadOnly::__set('test', 'write to me')
#1 C:\test.php(30): Writeable->__construct('write to me')
#2 {main}
thrown in C:\test.php on line 12
---------------test.php--------------
<?php
class ReadOnly {
protected $realProperty;
private $dynamicProperty = array();
function __construct() {
$realProperty = 12;
$this->dynamicProperty['test'] = 'read-only';
}
public function __set($name, $value) {
if($name=='test') {
if(isset($this->dynamicProperty[$name]))
throw new Exception("Can't overwrite $name");
$dynamicProperty[$name] = $value;
}
}
public function __get($name) { return $this->dynamicProperty[$name];
}
}
class Writeable extends ReadOnly {
function __construct($value) {
parent::__construct();
$this->realProperty = 25; // ok
$this->test = $value; // causes Fatal Error
}
public function getReal() {return $this->realProperty; }
public function getDynamic() {return $this->test; }
}
echo "testing...\r\n";
$test = new Writeable('write to me');
echo 'real: '.$test->getReal()."\r\n";
echo 'dynamic: '.$test->getDynamic()."\r\n";
?>
------------------------------------------------------------------------
[2005-11-04 12:38:17] [EMAIL PROTECTED]
Please try using this CVS snapshot:
http://snaps.php.net/php5-latest.tar.gz
For Windows:
http://snaps.php.net/win32/php5-win32-latest.zip
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
http://bugs.php.net/35104
--
Edit this bug report at http://bugs.php.net/?id=35104&edit=1