ID: 28444 Comment by: alexei at net24 dot co dot nz Reported By: dennis at inmarket dot lviv dot ua Status: Analyzed Bug Type: Class/Object related Operating System: WinXP PHP Version: 5.0.0RC2 New Comment:
it allows to read value referenced by $a->b->c but it does not allow to modify it, that's makes the whole thing inconsistent... workaround like below does the job, but it is ugly! $b=$a->b; $b->c=5; i think if ->-> is called it should call __get methods at all each stage and pass reference to the next -> operation Previous Comments: ------------------------------------------------------------------------ [2004-06-30 04:21:46] ryan dot harris at gmail dot com A good solution would be to have a way of doing a "pre-set" routine i.e. __get($propertyname, $pre_set = true) and that routine is expected to return a valid object or the "Cannot access undefined..." will automatically result. Some more example code that causes the problem (no way of testing to see if the concept is correct - since this message keeps appearing): class Setting { private $mSettings; function __construct() { $constructor_args = func_get_args(); if (isset($constructor_args[0])) { $this->mSettings = array("_defaultValue"=>$constructor_args[0]); } else $this->mSettings = array("_defaultValue"=>null); } function __get($propertyName) { print "[$propertyName]<br>\n"; if ($propertyName == "_settingCount") { return count($this->mSettings) - 1; } elseif ($propertyName == "_valueNames") { //return $this->GetValueNames(); } elseif ($propertyName == "_keyNames") { //return $this->GetValueNames(); } elseif ($propertyName == "_defaultValue") { print_r($this->mSettings); return $this->mSettings["_defaultValue"]; } // It's none of the special properties. if (isset($this->mSettings[$propertyName])) { return $this->mSettings[$propertyName]; } else { // If we had the $pre_set we could do this: if ($pre_set) { // initialize for a set $this->mSettings[$propertyName] = new Setting(); return $this->mSettings[$propertyName]; } else throw new Exception("Undefined setting name."); } } function __set($propertyName, $propertyValue) { print "[$propertyName]<br>\n"; switch ($propertyName) { case "_settingCount": case "_valueNames": case "_keyNames": throw Exception("Property is read only."); break; case "_defaultValue": $this->mSettings["_defaultValue"] = $propertyValue; break; default: if (!isset($this->mSettings[$propertyName])) $this->mSettings[$propertyName] = new Setting($propertyValue); else $this->mSettings[$propertyName]->_defaultValue = $propertyValue; break; } // switch } } This code if it worked would let you do the following: $t = new Setting(); $t->includes->_defaultValue = "Automated" $t->includes->automatedIncludes->includeDirectory = "c:/includes" $t->includes->automatedIncludes = "oncePerFile" $t->includes->manualIncludes->includeDirectory = "c:/php" Which would represent: includes = Automated --> automatedIncludes = oncePerFile --> includeDirectory = c:/includes --> manualIncludes --> includeDirectory = c:/php in a lightweight manner. The layers would be created as they are needed and all with an elegant method. ------------------------------------------------------------------------ [2004-06-14 20:24:14] cunha17 at uol dot com dot br This odd behavior is still present in latest CVS and happens in Linux also. Cristiano Duarte ------------------------------------------------------------------------ [2004-05-27 16:11:39] dennis at inmarket dot lviv dot ua Well, I am not familiar with the engine code, but it works for getting "undefined property for object with overloaded property access", as the reproduce code clearly shows. ------------------------------------------------------------------------ [2004-05-27 12:15:55] [EMAIL PROTECTED] The problem here is that it is unclear what actually should happen in this case. When executing $y->x->x = 3, we need to fetch $y->x for writing, i.e., get zval** of it. However, only handler that could give it to us is get_property_ptr_ptr and it is not overridable. We probably could use the result of __get, though it would mean we would have to fake zval**, which could have some strange consequences - needs to be checked. ------------------------------------------------------------------------ [2004-05-19 12:34:23] dennis at inmarket dot lviv dot ua Description: ------------ "Cannot access undefined property for object with overloaded property access" is an error when I try to set a property of an instance, which, in turn, is a property of another instance of an overloaded class, i.e. $a->x->y = 2 triggers the error if $a is an instance of an overloaded class. Note that getting that property works fine. Reproduce code: --------------- class Object { public $x; function __construct($x) { $this->x = $x; } } class Overloaded { var $props; function __construct($x) { $this->x = new Object($x); } function __get($prop) { return $this->props[$prop]; } function __set($prop, $val) { $this->props[$prop] = $val; } } $y = new Overloaded(2); echo $y->x->x, " "; // Prints 2... echo $y->x->x = 3; //Should print 3... Expected result: ---------------- 2 3 Actual result: -------------- 2 Fatal error: Cannot access undefined property for object with overloaded property access in path/to/script.php on line 22 ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=28444&edit=1