[原] PHP 踩坑实战第二坑:empty

    最近在同事在实践中踩到的一个 empty 坑。关于 empty 的判断类型,就不赘述了,网上解释有很多。例如:0, ”, false, null 等都会被判定为 true。

    这次的坑是 empty 对于对象私有属性的判断。我们来直接上代码:

    

<?php
class a
{
    private $a1 = '123';

    public function __get($name)
    {
        return $this->$name;
    }
}

$a = new a();
var_dump($a->a1,empty($a->a1));

// string(3) "123"
// bool(true)

    我们都知道 private 私有属性是无法在外部读取的。想要读取就需要使用 魔术方法 __get 。 这种场景也经常经常在各种框架中出现。

    从输出结果我们可以看出。读取是没有问题的。但是 empty 的判断却是 true。而我们再使用各种框架的时候,也经常如此直接判断,并没有该问题出现。那一定是框架背后做了一些什么。

    在 stackoverflow 上也有很多人对此提出了疑问,也找到了解决方案,结合框架源码,也确实如此。 那就是增加 __isset() 魔术方法。

public function __isset($property)
{
    return isset($this->$property);
}

    现在返回的结果是不是跟预期一致了呢?确实是。问题解决。那为什么? 

    根据 PHP 官方的解释:__isset() is triggered by calling isset() or empty() on inaccessible properties. 

    和直接在 __get、__isset 方法中增加输出测试。可以得出,如不增加 __isset 魔术方法(或者说如果该方法不返回 true)。那么 empty 的过程中,是不会调用 __get 进行获取数据的。没有取到数据,所以结果为 true。

    在 PHP 的源码中 empty 和 isset 最终调用的都是同一个方法。所以魔术方法也使用同样的 __isset 。

    同样的 对于私有属性进行 unset  同样需要 __unset 魔术方法。