如何为未在类中设置的属性及其子键返回null


How to return null for a property and its children keys that are not set in a class?

如何为属性及其子键返回null而不是在类中设置?

我可以使用__get使属性返回null,但我不知道如何为它的子键做到这一点。什么好主意吗?

class MyClass
{
    public $foo;
    public $bar;
    public function __construct()
    {
        $this->bar = (object) ['tool' => 'Here we go'];   
    }
    public function __get($name)
    {
        return (isset($this->$name)) ? $this->$name : null;
    }
}
$class1 = new MyClass;
var_dump($class1->foo); // null
var_dump($class1->boo); // null
var_dump($class1->bar->tool);  // 'Here we go'
var_dump($class1->bar->mars); // Notice: Undefined property: stdClass::$mars in...

$class1->bar->mars有可能得到null

不是将$this->bar转换为(object),这将是stdClass的一个实例(您无法控制),而是创建另一个类来表示您在$this->bar中存储的数据,并定义类似的__set()__get()方法。

的例子:

class KeyValuePairs {
    private $pairs;
    public function __construct( $arr = [])
    {
        $this->pairs = [];
        foreach( $arr as $k => $v) {
            $this->pairs[$k] = $v;
        }
    }
    public function __get($name)
    {
        return (isset($this->pairs[$name])) ? $this->pairs[$name] : null;
    }
    public function __set($name, $value)
    {
        $this->pairs[$name] = $value;
    }
}

然后你可以把__construct()改成:

public function __construct()
{
    $this->bar = new KeyValuePairs( ['tool' => 'Here we go']);   
}

得到:

$class1 = new MyClass;
var_dump($class1->foo); // null
var_dump($class1->boo); // null
var_dump($class1->bar->tool);  // 'Here we go'
var_dump($class1->bar->mars); // null

您不能神奇地做到这一点,我建议编写这样的代码是不好的做法。要么使用已定义的数据结构,要么没有。如果你不确定你的数据结构是什么样的,你不应该像->foo->bar->baz那样直接访问它。使用一些带有显式错误处理的代码。我建议:

class MyClass {
    public $values;
    public function __construct() {
        $this->values = ['tool' => 'Here we go'];   
    }
    public function get($name) {
        return array_reduce(explode('.', $name), function ($value, $key) {
            if (is_array($value) && array_key_exists($key, $value)) {
                return $value[$key];
            }
            return null;
        }, $this->values);
    }
}
$foo = new MyClass;
echo $foo->get('tool');
echo $foo->get('non.existent.key');

显然,使用明确定义的数据结构是最好的选择,这样您就可以确定这些键存在。如果您访问了一个不存在的键,PHP将抛出一个错误,因为它应该。