ID:               28444
 User updated by:  dennis at inmarket dot lviv dot ua
 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:

In my opinion, such "workarounds" should be replaced by fixing the
issue in PHP itself. Indeed, it is funny that this works for getting
properties, and doesn't for setting. Onother question: how did PHP5
make for a release with this core level bug?


Previous Comments:
------------------------------------------------------------------------

[2004-08-05 07:20:16] alexei at net24 dot co dot nz

another "workaround", it allows to use this feature now and
to convert scripts later when this feature is available in php.

class a {

function __call ($property, $args){
return __get($property);
}

use it like this:

$a->b->c=10; as $a->b()->c=10;
echo $a->b->c; as echo $a->b()->c;

------------------------------------------------------------------------

[2004-08-05 06:48:18] alexei at net24 dot co dot nz

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

------------------------------------------------------------------------

[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.

------------------------------------------------------------------------

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/28444

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

Reply via email to