MENU

PHP中魔术方法__set和__get的使用

2018 年 11 月 14 日 • PHP阅读设置

简介

在php中,有很多魔术方法,魔术方法都是以两个下划线 __ 开头的保留方法,这些魔术方法都是针对类而存在的。

  • __set: 给类不存在或者不可访问的属性赋值时会被自动调用
  • __get: 读取类不存在或者不可访问的属性时会被自动调用

二者的原型如下

public mixed __get ( string $name )
public void __set ( string $name , mixed $value )

例子

class A
{
    public $name;
}

$a = new A;
$a->name = 'zhangsan';
echo $a->name;

正常情况下,上面的代码会正确的输出zhangsan的结果,没有问题。
此时,假如输出对象a不存在的age属性,页面上会提示A::$age未定义。

echo $a->age;

Notice: Undefined property: A::$age

当然,有人可能会说,我声明一个public $a; 不就行了吗?可以呀,不过像你这样砸场子的话,我就没有继续说下去的必要了。

对A类增加一个 __get 方法,看看这个会被自动调用的方法是啥效果

class A
{
    public $name;

    public function __get($name)
    {
        var_dump($name);
    }
}

依然访问 $a->age 属性

echo $a->age;

其结果瞬间由刚才的Notice提醒变成了

string(3) "age"

你可以再写一个protectedprivate类型的属性,其结果跟不存在的age属性一样,会自动调用__get方法。但是 public类型的name属性不会调用该方法。

现在,再为A类增加一个__set方法

class A
{
    public $name;

    public function __get($name)
    {
        // var_dump($name);
    }

    public function __set($name, $value)
    {
        var_dump($name, $value);
    }
}

为不存在的属性age赋值,看看效果

$a = new A;
$a->age = 20;

结果如下

string(3) "age" int(20)

当然,protectedprivate类型的属性被赋值时也可以得到相同的结果,可以自己尝试下。
so easy,那么,我讲这些的意义是什么?
别急别急,鉴于以上,再看一个问题:
假如有一个B类以及一个配置数组如下

class B
{
    public $name;
}

$config = [
    'class' => 'B',
    'name' => 'zhangsan',
    'age' => 20,
];

如何根据$config的配置,来创建一个B对象并为B的对象属性赋值?
先思考一下再继续阅读哦。

B类的实现

class B
{
    public $name;

    private $_definitions = [];

    public function __get($name)
    {
        return isset($this->_definitions[$name]) ? $this->_definitions[$name] : null;
    }

    public function __set($name, $value)
    {
        $this->_definitions[$name] = $value;
    }
}

实例化上述类并通过$config为对象b赋值

$config = [
    'class' => 'B',
    'name' => 'zhangsan',
    'age' => 20,
];

$class = $config['class'];
unset($config['class']);

$object = new $class;

foreach ($config as $k => $v) {
    $object->$k = $v;
}

var_dump($object->name);
var_dump($object->age);

结果如下

string(8) "zhangsan" int(20)

这有点像什么?这是不是有点像yii2中的配置项?

返回文章列表 打赏
本页链接的二维码
打赏二维码