一直以来,在我的理解中,类的成员变量和属性就是同一个东西,直到看了《深入理解Yii2.0才明白,类的成员变量和属性其实不是同一个概念,成员变量是就类的结构构成而言的概念,而属性是就类的功能逻辑而言的概念,而且两者没有必然的对应关系。

类的成员变量有public、protected、private三种类型,其中public类型的成员变量可以视为可读可写的属性,而另外两种类型的成员变量都不是属性,因为属性应该是可以在类外面进行访问的。

在Yii2.0中,yii\base\Object类通过PHP的魔术方法__get()和__set()来提供对属性的支持,源码如下:

public function __get($name)
{
$getter = 'get' . $name;
if (method_exists($this, $getter)) {//存在对应的getter方法
return $this->$getter();
} elseif (method_exists($this, 'set' . $name)) {//只写属性
throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name);
} else {//属性不存在
throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name);
}
}
public function __set($name, $value)
{
$setter = 'set' . $name;
if (method_exists($this, $setter)) {//存在对应的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);
}
}

  在yii2.0中,如果一个类需要支持属性,只要继承yii\base\Object类即可,以下举例说明:

class user extends yii\base\Object {
public $name;
private $addr;
private $age;
public function getAddress() {
return $this->addr;
}
}

  这是一个很简单的类,根据类的成员变量和属性的概念可知,以上这个类中有三个成员变量:$name、$addr、$age,两个属性:$name、address。其中$name是可读可写属性,而address是只读属性,因为只存在getter方法而没有对应的setter方法。

  假如我们在user类外面创建一个对象$user,通过$user->address来读取user类的address属性的时候,其实是遍历了一下user类的所有成员变量,没有找到address属性对应的成员变量的时候,再去调用__get()方法看看是否存在对应的getter方法,有则调用它。可以看到,当类的某个属性没有对应的成员变量的时候,通过$user->address这种方式来访问属性虽然比较方便但效率是比较低的,而使用$user->getAddress() 直接调用getter方法访问属性则可以省去遍历类成员变量的过程,比较高效。

除了__get()和__set()之外,yii\base\Object类还提供了与属性相关的其他方法:

__isset():判断属性是否不为null。

__unset():将属性值设置为null。

hasProperty():判断是否存在某个属性。

canGetProperty():判断某个属性是否可读。

canSetProperty():判断某个属性是否可写。

在yii2.0中,创建一个对象的时候,怎么给对象的所有属性赋值呢?Yii2.0提供了一个统一的配置对象的方式,那就是使用一个键值对形式的配置数组。那么yii2.0又是怎么支持这种配置方式的呢?通过查看源码可以看到,yii\base\Object类的构造函数__construct()中调用了Yii::configure()方法,该方法源码如下:

public static function configure($object, $properties)
{
foreach ($properties as $name => $value) {
$object->$name = $value;
} return $object;
}

  其实很简单,就是遍历配置数组,配置数组的键名为对象的属性名,对应的值则作为属性值,逐一进行赋值。至于当对象的属性是对象或数组时,赋值操作该怎么进行就是setter函数的事了。

Yii2之属性的更多相关文章

  1. yii2知识点理解(成员属性)

    yii2成员属性 成员变量类似于public $a; 成员属性类似于 public function a(){} 成员变量是就类的结构构成而言的概念,而属性是就类的功能逻辑而言的概念 成员属性应用: ...

  2. Yii2之组件的注册与创建

    今天本来打算研究一下yii2.0的AR模型的实现原理,然而,计划赶不上变化,突然就想先研究一下yii2.0的数据库组件创建的过程.通过对yii源码的学习,了解了yii组件注册与创建的过程,并发现原来y ...

  3. Yii2基本概念之——配置(Configurations)

    在Yii中创建新对象或者初始化已经存在的对象广泛的使用配置,配置通常包含被创建对象的类名和一组将要赋值给对象的属性的初始值,这里的属性是Yii2的属性.还可以在对象的事件上绑定事件处理器,或者将行为附 ...

  4. jqu

    1 /*2 * 说明:3 * 本源代码的中文注释乃Auscarlin呕心沥血所作.旨在促进jQuery的传播以及向广大jQuery爱好者提供一个进阶4 *的途径,以让各位更加深入地了解jQuery,学 ...

  5. Yii2基本概念之——属性(property)

    学习任何一门学问,往往都是从起基本的概念学起.万丈高楼平地起,这些基本概念就是高楼的基石,必须做详尽的分析.我们知道,Yii2是一款脉络清晰的框架,理顺了基础的概念和基本功能,学习更高级和复杂的功能就 ...

  6. Yii2给数据库表添加字段后对应模型无法识别到该属性的原因和解决办法

    Yii2给数据库表添加字段后对应模型无法识别到该属性的原因和解决办法 应为数据库表的结构被缓存了.删除runtime文件夹或者执行 //清理指定表结构缓存数据 Yii::$app->db-> ...

  7. yii2:属性

    yii2:属性 在 PHP 中,类的成员变量也被称为属性(properties). 以Foo.php类文件为例: 继承yii\base\Object类(基于类内的 getter 和 setter(读取 ...

  8. Yii2 提供可以用属性的方式去获取类的一个方法

    刚开始用 Yii 的小朋友可能对下面的写法非常疑惑: public function actionIndex() { $user = User::find()->where(['name'=&g ...

  9. [moka同学笔记]Yii2.0给一张表中增加一个属性

    1.model中建立关联 public function getUser(){ return$this->hasOne(User::className(),['id'=>'uid']) ; ...

随机推荐

  1. php memcache 扩展 php -m 与 phpinfo() 不同

    事情起因,因要升级 openssl(openssl升级这里不表) ,所以在升级后对 php 也进行了从新编译,编译成功. 发现没有安装,memcache 扩展,从新编译安装了一下,显示的安装成功,但是 ...

  2. Ajax【介绍、入门、解决Ajax中文、跨域、缓存】

    什么是Ajax Ajax(Asynchronous JavaScript and XML) 异步JavaScript和XML Ajax实际上是下面这几种技术的融合: (1)XHTML和CSS的基于标准 ...

  3. JavaScript中DOM

    概念 什么是DOM 1. 什么是 DOM DOM 的全称是document object model 它的基本思想是将结构化文佳例如HTML xml解析成一系列的节点.就像一颗树一样. 所有的节点和最 ...

  4. JMeter基础之—录制脚本

    Jmeter 是一个非常流行的性能测试工具,虽然与LoadRunner相比有很多不足,比如:它结果分析能力没有LoadRunner详细:很它的优点也有很多: l       开源,他是一款开源的免费软 ...

  5. Unity GameObject Class

    GameObject  Note : gameObject 指的是当前挂着的对象. class in UnityEngine / Inherits from:Object     Descriptio ...

  6. 用static声明的函数和变量小结

    static 声明的变量在C语言中有两方面的特征: 1).变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值.这一点是它与堆栈变量和堆变量的区别. 2).变量用static ...

  7. GCD之异步同步体会

    前面的博文也有写到同步异步,可能是看他人的博文,自己没有实验,感觉理解不深,所以就敲了些代码比较一下串行.并行分别对应的同步.异步. 1.首先创建串行.并行线程队列 1 2 dispatch_queu ...

  8. 为什么要用深度学习来做个性化推荐 CTR 预估

    欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:苏博览 深度学习应该这一两年计算机圈子里最热的一个词了.基于深度学习,工程师们在图像,语音,NLP等领域都取得了令人振奋的进展.而深 ...

  9. 封装好的图片滑动框架(AndroidImageSlider)

    前言 广告轮播条的重要性不言而喻.在很多类型app中出场率都很高. 今天给大家介绍一个轮播图开源项目,这个项目把轮播图需要的ViewPager跟计时器做了封装,使用极其方便,支持gradle在线依赖. ...

  10. (转)C#中各种集合类比较

    数组(Array)的不足(即:集合与数组的区别) 1. 数组是固定大小的,不能伸缩.虽然System.Array.Resize这个泛型方法可以重置数组大小,但是该方法是重新创建新设置大小的数组,用的是 ...