浅析Yii20的属性Property

27次阅读

共计 1963 个字符,预计需要花费 5 分钟才能阅读完成。

概念理解:第一次看深入理解 Yii2.0 的时候,我也是懵逼的,属性不就是类的属性吗,有什么好说的。后来才知道 Yii 框架对成员变量和属性做了区分,那类的成员变量和属性到底是什么关系又有什么区别呢?先看一下比较书面化的说法,” 成员变量是就类的结构构成而言的概念,而属性是就类的功能逻辑而言的概念,两者紧密联系又相互区别 ”。说白点就是属性是业务上抽象出来的概念,并且属性的代码实现依赖于成员变量,但不能说属性就是成员变量,(好像也不是很直白 …)并且属性在代码上可以做到控制读写权限,而成员变量就不可以了。

属性的实现步骤

  • 继承自 yii\base\BaseObject
  • 声明一个用于保存该属性的私有成员变量。
  • 提供 gettersetter函数,或两者都提供,用于访问、修改上面提到的私有成员变量。如果只提供了getter,那么该属性为只读属性,只提供了setter,则为只写。

属性的实现 demo

<?php

namespace common\components;

use yii\base\BaseObject;


class Article extends BaseObject
{
    // 成员变量
    private $_val = '我是初始值';

    // 控制属性读权限的方法
    public function getTitle()
    {return $this->_val;}

    // 控制属性写权限的方法
    public function setTitle($value)
    {$this->_val = $value;}
}

$obj = new Article();

// 获取属性文章标题的值
$obj->title;                            

// 设置属性文章标题的值
$obj->title = 'mysql 从入门到删库';        
        
注意:上述 demo 中,$_val 就是成员变量 title 就是一个抽象出来的业务属性。从 Yii2.0.13 以后推荐继承的是 yii\base\BaseObject,而不是 yii\base\Object 因为在 php7.2 以后 Object 是保留字,不能再作为类名

那么 Yii 是怎么通过 getTitle()setTitle()函数来控制属性 title 的读写的呢?其实很简单,通过 __get()__set()俩个魔术方法来实现的。

属性的实现原理

下面是类 BaseObject 里面对于 __set()__get()魔术方法的实现。

    public function __get($name)
    {
        $getter = 'get' . $name;
        if (method_exists($this, $getter)) {return $this->$getter();
        } elseif (method_exists($this, 'set' . $name)) {throw new InvalidCallException('Getting write-only property:' . get_class($this) . '::' . $name);
        }

        throw new UnknownPropertyException('Getting unknown property:' . get_class($this) . '::' . $name);
    }

    public function __set($name, $value)
    {
        $setter = 'set' . $name;
        if (method_exists($this, $setter)) {$this->$setter($value);
        } elseif (method_exists($this, 'get' . $name)) {throw new InvalidCallException('Setting read-only property:' . get_class($this) . '::' . $name);
        } else {throw new UnknownPropertyException('Setting unknown property:' . get_class($this) . '::' . $name);
        }
    }
    

当我们读取类 Article 实例里面 title 值的时候,会去遍历类 Article 里面的属性,找不到匹配的属性的时候,就会自动触发 __get() 魔术方法 [注: 当调用当前环境下未定义或不可见的类属性时自动触发],在__get() 方法里再去调用 getTitle() 方法。设置属性 title 同理。[注: 由于 PHP 对于类方法不区分大小写,即大小写不敏感,$obj->getTitle() 和 $obj->gettitle() 是调用相同的函数]

小结

以上总结参考了深入理解 Yii2.0[这次可能参考的比较多,嘿嘿],其实以前就看过,但是也只是局限于看过,没有自己跑 demo 调试、查看源代码,然后就误以为自己明白了,其实过俩天什么都不记得了。所以现在通过写博客来加深自己的理解,由于水平有限,欢迎小伙伴交流和指正。

正文完
 0