之前我们说过Yii2 中大多数类都继承自 yiiaseObject,今天就让我们来看一下这个类。
Object 是一个基础类,实现了属性的功能,其基本内容如下:
<?phpnamespace yiiase;use Yii;/** * Object 是一个基础类,实现了属性的功能 * Yii最基础的类,大多数类都继承了该类 */html' target='_blank'>class Object implements Configurable{ /** * 获取静态方法调用的类名。返回类的名称,如果不是在类中调用则返回 FALSE。 */ public static function className() { ... } /** * Constructor. */ public function __construct($config = []) { ... } /** * 初始化对象 */ public function init() { } /** * 魔术方法,实现 getter */ public function __get($name) { ... } /** * 魔术方法,实现 setter */ public function __set($name, $value) { ... } /** * 魔术方法,实现 isset,基于 getter 实现,有 getter 方法的属性才算存在 */ public function __isset($name) { ... } /** * 魔术方法,实现 unset,基于 setter 实现,有 setter 方法的属性才能 unset 掉 */ public function __unset($name) { ... } /** * Calls the named method which is not a class method. */ public function __call($name, $params) { ... } /** * 检查对象或类是否具有 $name 属性,如果 $checkVars 为 true,则不局限于是否有 getter/setter */ public function hasProperty($name, $checkVars = true) { ... } /** * 检查对象或类是否能够获取 $name 属性,如果 $checkVars 为 true,则不局限于是否有 getter */ public function canGetProperty($name, $checkVars = true) { ... } /** * 检查对象或类是否能够设置 $name 属性,如果 $checkVars 为 true,则不局限于是否有 setter */ public function canSetProperty($name, $checkVars = true) { ... } /** * 检查对象或类是否具有 $name 方法 */ public function hasMethod($name) { ... }}
如果想看详细的注释的话,可以访问https://github.com/ReadCode/yii2-2.0.3-annotated/blob/master/framework/base/Object.php
从上面的内容中,我们可以看到 Object 类重写了__get和 __set 方法,下面我们来详细看下这两个方法:
/** * Returns the value of an object property. * * Do not call this method directly as it is a PHP magic method that * will be implicitly called when executing `$value = $object->property;`. * * 魔术方法,实现 getter * * @param string $name the property name * @return mixed the property value * @throws UnknownPropertyException if the property is not defined * @throws InvalidCallException if the property is write-only * @see __set() */ public function __get($name) { $getter = 'get' . $name; if (method_exists($this, $getter)) { // 对象存在 $getter 方法,就直接调用 return $this->$getter(); } elseif (method_exists($this, 'set' . $name)) { // 如果存在 'set' . $name 方法,就认为该属性是只写的 throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name); } else { // 否则认为该属性不存在 throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name); } } /** * Sets value of an object property. * * Do not call this method directly as it is a PHP magic method that * will be implicitly called when executing `$object->property = $value;`. * * 魔术方法,实现 setter * * @param string $name the property name or the event name * @param mixed $value the property value * @throws UnknownPropertyException if the property is not defined * @throws InvalidCallException if the property is read-only * @see __get() */ public function __set($name, $value) { $setter = 'set' . $name; if (method_exists($this, $setter)) { // 对象存在 $setter 方法,就直接调用 $this->$setter($value); } elseif (method_exists($this, 'get' . $name)) { // 如果存在 'get' . $name 方法,就认为该属性是只读的 throw new InvalidCallException('Setting read-only property: ' . get_class($this) . '::' . $name); } else { // 否则认为该属性不存在 throw new UnknownPropertyException('Setting unknown property: ' . get_class($this) . '::' . $name); } }
基于上面的代码,我们可以看到,如果访问一个 Object 对象的某个属性, Yii会调用名为get属性名()的函数。如,SomeObject->Foo, 会自动调用SomeObject->getFoo()。 如果修改某一属性,会调用相应的setter函数。 如,SomeObject->Foo=$someValue,会自动调用SomeObject->setFoo($someValue)。
以SomeObject 的 Foo 为例,如果只存在getFoo() 方法,那它就是只读的,如果只存在setFoo() 方法,那它就是只写的,只有两个方法都存在的时候才是既可读又可写的。
需要注意的一点是只有在读取和写入对象的一个不存在的成员变量时,__get()__set()会被自动调用。 如果 Foo 是一个 public 的属性就不会经过__get() 和__set() 方法了。
所以通常属性是 private 的,举个例子如下:
class User extends yiiaseObject{ private $_name; public function getName() { return $this->_name; } public function setName($name) { $this->_name = trim($name); }}
我们还可以在 get 和 set 方法中做一些特殊的处理。
除了__get()__set()之外,yiiaseObject还提供了以下方法便于使用属性:
对 Yii2 源码有兴趣的同学可以关注项目yii2-2.0.3-annotated,现在在上面已经添加了不少关于 Yii2 源码的注释,之后还会继续添加~
PHP编程郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。
新闻热点
疑难解答