Page 1 of 1

Limitation of Variable Method Syntax

Posted: Tue Aug 01, 2006 6:20 pm
by Ollie Saunders

Code: Select all

class A
{
    public $b;
    public function __construct()
    {
        $this->b = new B();
    }
}

class B
{
    public $z = 10;
}

$a = new A();
$prop = 'b->z';
$a->$prop = 20;

echo $a->b->z;
Doesn't trigger an error,
Doesn't assign $a->b->z to 20,
Just leaves it as $a->b->z as 10.

If I want to do this I have to use reflection do I?
Using PHP 5.1.2

Posted: Tue Aug 01, 2006 6:29 pm
by feyd
for an interesting treat, var_dump($a) ;)

Code: Select all

[feyd@home]>php -r "class a { public $b; public function __construct() { $this->b = new b(); } } class b { public $z = 10; } $a = new a(); $prop = 'b->z'; $a->$prop = 20; var_dump($a); $a = new a(); $prop = array('b','z'); $c =& $a; foreach($prop as $r) { $c =& $c->$r; } $c = 20; var_dump($a);"
object(a)#1 (2) {
  ["b"]=>
  object(b)#2 (1) {
    ["z"]=>
    int(10)
  }
  ["b->z"]=>
  int(20)
}
object(a)#3 (1) {
  ["b"]=>
  &object(b)#4 (1) {
    ["z"]=>
    &int(20)
  }
}

Posted: Tue Aug 01, 2006 6:39 pm
by Ollie Saunders

Code: Select all

<?php
class A
{
    public $b;
    public function __construct()
    {
        $this->b = new B();
    }
    /**
     * Set a public attribute to a value. Returns whether it could be set or not
     *
     * @param string $name
     * @param string [,..$name]
     * @param mixed $value
     * @return bool
     */
    public function set()
    {
        $args = func_get_args();
        $value = array_pop($args);
    
        $propertyChain = implode('->', $args);
        $reflection = new ReflectionProperty($this, $args[0]);
        if ($reflection->isPublic()) {
            if (is_string($value)) {
                $value = '\'' . addcslashes($value, '\'') . '\'';
            }
            eval('$this->' . $propertyChain . ' = ' . $value . ';');
            return true;
        }
        return false;
    }
}

class B
{
    public $z = 10;
}

$a = new A();
$a->set('b', 'z', 20);

echo $a->b->z;

?>
seems to work :)

Posted: Tue Aug 01, 2006 6:40 pm
by Ollie Saunders
Feyd wrote:

Code: Select all

object(b)#2 (1) {
    ["z"]=>
    int(10)
  }
  ["b->z"]=>
  int(20)
Oh wow!
That makes sense.