Robert
Robert

Reputation: 10380

php object oriented overloading

I came across the following code and could not figure out why the output of the script came out in a non-intuitive sequence using php's get and set magic methods.

class Magic
{
    public $a = "A";
    protected $b = array("a" => "A", "b" => "B", "c" => "C");
    protected $c = array(1,2,3);

    public function __get($v)
    {
        echo "$v";
        return $this->b[$v];
    }
    public function __set($var, $val)
    {
        echo "$var: $val";
        $this->$var = $val;
    }
}
$m = new Magic();
echo $m->a . "," . $m->b . "," . $m->c . ",";
$m->c = "CC";
echo $m->a . "," . $m->b . "," . $m->c;

Out put was:

bcA,B,C,c
CCbcA,B,C

First of all why is it no outputting A as the first thing? The sequence of output doesn't make sense.

Upvotes: 1

Views: 194

Answers (3)

crush
crush

Reputation: 17013

echo $m->a . "," . $m->b . "," . $m->c . ",";

When this line gets called, it is first resolving variable names before the concatenation takes place.

So it looks up $m->a, then $m->b, then $m->c.

Since $m->a resolves to your public property a, it doesn't trigger your _get, thus that echo in there doesn't get sent right away. However, $m->b does trigger it, which causes it to get echoed.

Finally, once the variables are resolved, the whole concatenated string gets output.

Upvotes: 0

Leri
Leri

Reputation: 12535

The reason is quite simple. You do string concatenation so PHP has to prepare complete string before outputs one. It means that it executes everything that needs to be concatenated. When it executes getter (__get method will be called only for inaccessible members) there's echo that is executed first and then returned value.

If you echo them out separately everything will be on its place.

Upvotes: 1

juco
juco

Reputation: 6342

Somebody is studying for their Zend certification ;-)

The reason is that magic methods are only triggered when the property is inaccessible.

So, for the first echo, it fetches $m->a this is an accessible property, so it is not echo'd from __get and is simply returned. After this, both $b and $c are inaccessible, so they are echo'd and then returned.

So the output from the first echo is:

b // echo'd by __get
c // echo'd by __get
A // simply returned, and echo'd in the concatenated string
B // (As above)
C // (As above)

Upvotes: 1

Related Questions