ID: 35104 User updated by: php at tjworld dot net Reported By: php at tjworld dot net Status: Open Bug Type: Class/Object related Operating System: Windows 2003 PHP Version: 5.1.0RC5 New Comment:
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'); ?> Previous Comments: ------------------------------------------------------------------------ [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 ------------------------------------------------------------------------ [2005-11-04 11:49:33] php at tjworld dot net Description: ------------ When extending a class that has a visible (public or protected) read-only dynamic property by virtue of __set(), the sub-class is prevented from modifying (or "overloading") the property as if it were merely a public consumer of an instance-object of super, rather than an extension of the class definition itself. This shows up in particular in the DOM classes DOMNode and DOMDocument, where it causes: Fatal error: extDOMElement::__construct() [function.--construct]: Cannot write property in... If you extend both classes, and try to create a new derived extDOMNode object using a custom extDOMDocument->createElement(), it is impossible to set any of the new extDOMNode's dynamic properties from within extDOMNode's constructor (especially ownerDocument) because DOMNodes without an owner are forced to be read-only. The extDOMNode class definition should be able to modify the publically visible ownerDocument property. Since real properties accessible from a sub-class can't be private (if they're to be accessible from other objects), it follows that the same rule should apply to dynamic properties. If this were so the dynamic properties made visible by __set() would be inherited as protected or public and this issue wouldn't arise. Reproduce code: --------------- class ReadOnly { protected $realProperty; private $dynamicProperty = array(); function __construct() { $realProperty = 12; $this->members['test'] = 'read-only'; } public function __set($name, $value) { if($name=='test') { if(isset($this->dynamicProperty[$name])) throw new Exception("Can't overwrite $name"); $props[$name] = $value; } } } class Writeable extends ReadOnly { function __construct($value) { parent::__construct(); $this->realProperty = 25; // ok $this->test = $value; // causes Fatal Error } } $test = new Writeable('write to me'); Expected result: ---------------- The extended class should be able to inherit and modify protected or public properties of the super class. Actual result: -------------- For built-in classes causes a Fatal Error. For user defined classes causes a user-defined read-only result. In the example causes an Exception. ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=35104&edit=1