Ambiguous syntax of $this->$variable in PHP

435 views Asked by At

Please excuse me if this question has been asked before, but I tried searching for it with no satisfactory results.

I'm learning PHP (coming from a C++ background) and have come across the following ambiguity. The following two bits of code work exactly the same:

class A
{
    public $myInteger;
    public function __get($name) 
    { 
        return $this->$name; 
    }
    public function __set($name, $value)
    {
        $this->$name = $value;
    }
}

and

class A
{
    public $myInteger;
    public function __get($name) 
    { 
        return $this->name; 
    }
    public function __set($name, $value)
    {
        $this->name = $value;
    }
}

that is, in the class methods $this->$name and $this->name have the exact same function. I'm finding this a bit confusing, especially when considering that if you add the following code,

$myA = new A();
$myA->myInteger = 5;
$hereInt = $myA->myInteger;

echo "<p>" . $hereInt . "</p>";

it only works if there is no $ before myInteger. Could someone please explain the rationale behind this?

1

There are 1 answers

4
Will Vousden On BEST ANSWER

$this->$name and $this->name do not mean the same thing. The first is using a locally scoped variable $name to access the field of $this whose name is whatever $name contains, while the second accesses the name field directly.

For example, the following will output something:

$foo = new stdClass;
$foo->bar = 'something';

$baz = 'bar';
echo $foo->$baz;

In the case of __get and __set, $name contains the name of the property that was accessed at the call site; in your case, myInteger.

In your example, the __get and __set methods are actually superfluous, since $myA->myInteger is public and can be accessed directly. __get and __set are only needed to catch access attempts to a property that is not declared explicitly in the class.

For example, you might have a backing array that allows arbitrary "properties" to be set dynamically:

class Foo
{
    private $_values = array();

    public function __get($key)
    {
        if (isset($this->_values[$key]))
        {
            return $this->_values[$key]
        }
    }

    public function __set($key, $value)
    {
        $this->_values[$key] = $value;
    }
}

One thing that's somewhat confusing about this aspect of PHP's syntax is that a $ precedes a field declaration in a class, but there is none when accessing that field. This is compounded by the syntax for accessing static fields, which does require a $!