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

Reply via email to