Search code examples
phpmagic-methods

How to implements _isset magic method?


I try to implement the __isset magic method such as the following code,

Why do I always get an undefined index error? can anyone tell me how to do?

class c {
    public $x = array();
    public function __get($name) {
        return $this->x[$name]; //undefined index: #1:a / #2:b / #3:d
    }
    public function __isset($name) {
        return isset($this->x[$name]);
    }
}

$c = new c;
var_dump(isset($c->a));      
var_dump(isset($c->a->b));   #1
var_dump(isset($c->b->c));   #2
var_dump(isset($c->d['e'])); #3

Why the following code is working fine? I don't understand?

$x = array();
var_dump(isset($x->a->b->c));       
var_dump(isset($x['a']['b']['c']));

Solution

  • You might expect, that the PHP engine will call __isset() before every access to hidden properties in PHP. But thats not true. Check the documentation:

    __isset() is triggered by calling isset() or empty() on inaccessible properties.

    So, that's expected behaviour, as only:

    var_dump(isset($c->a));
    

    will trigger __isset().

    All of the other lines will just trigger __get(). And as you didn't set those indexes it is expected behaviour.

    Change your code to:

    class c {
        public $x = array();
        public function __get($name) {
            var_dump(__METHOD__);
            return $this->x[$name];
        }
        public function __isset($name) {
            var_dump(__METHOD__);
            return isset($this->x[$name]);
        }
    }
    

    to see which methods are actually called. This will give you:

    c::__isset   <------ called!
    bool(false)
    c::__get
    
    Notice: Undefined index: a in /tmp/a.php on line 6
    
    Call Stack:
        0.0002     647216   1. {main}() /tmp/a.php:0
        0.0003     648472   2. c->__get() /tmp/a.php:16
    
    <---------------------- not called 
    bool(false)
    c::__get
    
    Notice: Undefined index: b in /tmp/a.php on line 6
    
    Call Stack:
        0.0002     647216   1. {main}() /tmp/a.php:0
        0.0005     648656   2. c->__get() /tmp/a.php:17
    
    <---------------------- not called     
    bool(false)
    c::__get
    
    Notice: Undefined index: d in /tmp/a.php on line 6
    
    Call Stack:
        0.0002     647216   1. {main}() /tmp/a.php:0
        0.0006     648840   2. c->__get() /tmp/a.php:18
    
    <---------------------- not called     
    bool(false)