之前我們說過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編程鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。
新聞熱點
疑難解答