一直以来,在我的理解中,类的成员变量和属性就是同一个东西,直到看了《深入理解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. 201521123089 《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-21.1 截图你的提交结果(出现 ...

  2. tsst

    import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Sc ...

  3. Hyperledger Fabric 1.0 从零开始(三)——环境构建(内网/准离线)

    有公网环境的服务器可以直接看 Hyperledger Fabric 1.0 从零开始(二)--环境构建(公网) ,本篇内容与上篇相似,只不过环境搭建需要在内网下,也就是网络被限制的情况下. 1:环境构 ...

  4. Python爬虫总结

    Python爬虫的原理:1通过URLopen()来获取到url页面, 这个过程可以加代理 2这个页面上都是字符串,所以我们而通过字符串查找的方法来获取到目标字符串,用到了正则来匹配目标re.finda ...

  5. codeforces 862B B. Mahmoud and Ehab and the bipartiteness

    http://codeforces.com/problemset/problem/862/B 题意: 给出一个有n个点的二分图和n-1条边,问现在最多可以添加多少条边使得这个图中不存在自环,重边,并且 ...

  6. getOutputStream() has already been called for this response

    错误日志里偶尔会有getOutputStream() has already been called for this response这个错误 最近发现了高概率复现条件,所以顺手解决了一下: 首先根 ...

  7. MVC查询数据接收及校验

    本来想写一篇aspx的TreeView控件绑值的文章的,在写案例的时候,写了一半,发现有些地方还得考虑以下,就留待下次了. 这一篇的话,是最近在开发一个项目的时候,有大量的页面和数据表,需要花式查询, ...

  8. [转]HDFS HA 部署安装

    1. HDFS 2.0 基本概念 相比于 Hadoop 1.0,Hadoop 2.0 中的 HDFS 增加了两个重大特性,HA 和 Federaion.HA 即为 High Availability, ...

  9. 通过JQuery实现Ajax代码

    今天早上遇到了这个问题,结果我写的顺序是惨不忍睹啊,所有现在留个模版以示标准. $(function(){ $.ajax({ url : "Servlet", //传地址 type ...

  10. 如何将解压版的tomcat设置为windows 服务启动

    在web服务器上通常需要是web容器随开机自动启动,恰好Tomcat可以作为服务启动,只要经过我们简单的配置,就可以将免安装版的Tomcat添加到系统服务中. 首先需要配置以下环境变量: JAVA_H ...