Code explaining problem
Consider private/protected property, not initialized like:
private string $foo
Then add public method to check state like:
public function test_isset()
{
var_dump(isset($this->foo)); // false
unset($this->foo);
var_dump(isset($this->foo)); // false
}
Seems normal, right?
Ok, but now, add __isset() to the class, and run test_isset() again:
public function __isset($name)
{
echo "__isset\n";
return isset($this->foo);
}
Why, from now on, the result will be:
false
__isset
false
Question
What I assumed was that isset can't trigger the magic __isset() within the same class.
But that didn't happen. It turns out that isset() can't know about itself, meaning it calls the magic method when the property doesn't exist.
But then, if I can't call myself within myself, why does this only happen when this __isset() exists?
After all, the first time this __isset() didn't exist, the second isset() in test_isset executed and return false. So, it turns out that the presence of __isset() changes the behavior of isset() within the method. Why?
Secondly, why doesn't isset() in __isset() call __isset() again and loop?
What is this:
isset($this->foo);
differs from this:
isset($this->foo)
Because one is in test_isset() and called __isset(),
and the other is in __isset() and returned false.
Why, then, is there such an inconsistency?
Extra.
Adding another intermediate method that is called in __isset(), e.g., like this:
public function __isset($name)
{
var_dump('__isset');
return $this->checkIfExist($name);
}
private function checkIfExist($name)
{
var_dump('checkIfExist');
return isset($this->name);
}
The trace will be:
- test_isset - isset() returns false;
- unset();
- test_isset - isset() calls __isset();
- __isset() -> calls checkIfExists
- checkIfExists - isset() calls __isset()
- __isset() -> calls checkIfExists
- checkIfExists - isset() return false
So checkIfExists() was called twice, but once calls __isset, and once returns false.