首先你要知道什麼是php的魔術方法,它不是變魔術的,如果你想學習變魔術來錯地方了哦! 定義:PHP 將所有以 __(兩個下劃線)開頭的類方法保留為魔術方法。所以在定義類方法時,除了上述魔術方法,建議不要以 __ 為首碼。 作用:利用模式方法可以輕鬆實現PHP面向對象中重載(Overloading即動 ...
首先你要知道什麼是php的魔術方法,它不是變魔術的,如果你想學習變魔術來錯地方了哦!
定義:PHP 將所有以 __(兩個下劃線)開頭的類方法保留為魔術方法。所以在定義類方法時,除了上述魔術方法,建議不要以 __ 為首碼。
作用:利用模式方法可以輕鬆實現PHP面向對象中重載(Overloading即動態創建類屬性和方法)
其實很多博客主已經寫過這些方法了、、、但是我還是要說一遍。。誰讓你來聽了呢,碼這麼多字也不容易看完再走吧!
1.__construct,__destruct
__constuct構建對象的時被調用;
__destruct明確銷毀對象或腳本結束時被調用;
class Foo { private $name; private $link; public function __construct($name) { $this->name = $name; } public function __destruct() { echo 'Destroying: ', $this->name, PHP_EOL;//PHP_EOL代表php的換行符 } }
打住,先安利一波重載的定義及使用方法:
定義:PHP所提供的"重載"(overloading)是指動態地"創建"類屬性和方法。(我們是通過魔術方法(magic methods)來實現的)
作用:當調用當前環境下未定義或不可見的類屬性或方法時,重載方法會被調用。後面將使用"不可訪問屬性(inaccessible properties)"和"不可訪問方法(inaccessible methods)"來稱呼這些未定義或不可見的類屬性或方法。
註意:所有的重載方法都必須被聲明為 public。
2.__get、__set、__isset、__unset、__call、__callStatic //為啥放一起呢?
__set當給不可訪問或不存在屬性賦值時被調用
__get讀取不可訪問或不存在屬性時被調用
__isset對不可訪問或不存在的屬性調用isset()或empty()時被調用
__unset對不可訪問或不存在的屬性進行unset時被調用
__call調用不可訪問或不存在的方法時被調用
__callStatic調用不可訪問或不存在的靜態方法時被調用
Example #1 使用 __get(),__set(),__isset() 和 __unset() 進行屬性重載
<?php class PropertyTest { /** 被重載的數據保存在此 */ private $data = array(); /** 重載不能被用在已經定義的屬性 */ public $declared = 1; /** 只有從類外部訪問這個屬性時,重載才會發生 */ private $hidden = 2; public function __set($name, $value) { echo "Setting '$name' to '$value'\n"; $this->data[$name] = $value; } public function __get($name) { echo "Getting '$name'\n"; if (array_key_exists($name, $this->data)) { return $this->data[$name]; } $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } /** PHP 5.1.0之後版本 */ public function __isset($name) { echo "Is '$name' set?\n"; return isset($this->data[$name]); } /** PHP 5.1.0之後版本 */ public function __unset($name) { echo "Unsetting '$name'\n"; unset($this->data[$name]); } /** 非魔術方法 */ public function getHidden() { return $this->hidden; } } echo "<pre>\n"; $obj = new PropertyTest; $obj->a = 1; echo $obj->a . "\n\n"; var_dump(isset($obj->a)); unset($obj->a); var_dump(isset($obj->a)); echo "\n"; echo $obj->declared . "\n\n"; echo "Let's experiment with the private property named 'hidden':\n"; echo "Privates are visible inside the class, so __get() not used...\n"; echo $obj->getHidden() . "\n"; echo "Privates not visible outside of class, so __get() is used...\n"; echo $obj->hidden . "\n"; ?>
看完了嗎?好好看!
5.__sleep,__wakeup
__sleep當使用serialize時被調用,當你不需要保存大對象的所有數據時很有用
__wakeup當使用unserialize時被調用,可用於做些對象的初始化操作
<?php class Connection { protected $link; private $server, $username, $password, $db; public function __construct($server, $username, $password, $db) { $this->server = $server; $this->username = $username; $this->password = $password; $this->db = $db; $this->connect(); } private function connect() { $this->link = mysql_connect($this->server, $this->username, $this->password); mysql_select_db($this->db, $this->link); } public function __sleep() { return array('server', 'username', 'password', 'db'); } public function __wakeup() { $this->connect(); } } ?>
6.__clone
進行對象clone時被調用,用來調整對象的克隆行為
<?php class SubObject { static $instances = 0; public $instance; public function __construct() { $this->instance = ++self::$instances; } public function __clone() { $this->instance = ++self::$instances; } } class MyCloneable { public $object1; public $object2; function __clone() { // 強制複製一份this->object, 否則仍然指向同一個對象 $this->object1 = clone $this->object1; } } $obj = new MyCloneable(); $obj->object1 = new SubObject(); $obj->object2 = new SubObject(); $obj2 = clone $obj; print("Original Object:\n"); print_r($obj); print("Cloned Object:\n"); print_r($obj2); ?>
7.__toString
當一個類被轉換成字元串時被調用
<?php class SubObject { static $instances = 0; public $instance; public function __construct() { $this->instance = ++self::$instances; } public function __clone() { $this->instance = ++self::$instances; } } class MyCloneable { public $object1; public $object2; function __clone() { // 強制複製一份this->object, 否則仍然指向同一個對象 $this->object1 = clone $this->object1; } } $obj = new MyCloneable(); $obj->object1 = new SubObject(); $obj->object2 = new SubObject(); $obj2 = clone $obj; print("Original Object:\n"); print_r($obj); print("Cloned Object:\n"); print_r($obj2); ?>
8.__set_state
當調用var_export()導出類時,此靜態方法被調用。用__set_state的返回值做為var_export的返回值。
<?php class A { public $var1; public $var2; public static function __set_state($an_array) // As of PHP 5.1.0 { $obj = new A; $obj->var1 = $an_array['var1']; $obj->var2 = $an_array['var2']; return $obj; } } $a = new A; $a->var1 = 5; $a->var2 = 'foo'; eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array( // 'var1' => 5, // 'var2' => 'foo', // )); var_dump($b); ?>
enmmm,我知道你記不住的。。這麼多誰記得住啊,好煩啊、、、別,這還沒講完呢,更多方法請參考PHP的官方文檔:http://php.net/manual/zh/,別打我,你自己去看吧,畢竟好東西還是要眾樂樂的!了;另外這些代碼你最好再編譯器中運行一邊,不然看完你估計和沒看一個樣2333 ····
作者原創、轉載請註明出處