Limitation of Variable Method Syntax

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Limitation of Variable Method Syntax

Post 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
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post 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)
  }
}
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post 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 :)
Last edited by Ollie Saunders on Tue Aug 01, 2006 7:22 pm, edited 1 time in total.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Feyd wrote:

Code: Select all

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