PHP中魔術方法的定義是把以兩個底線__開頭的方法稱為魔術方法,這些魔術方法在PHP中的作用是非常重要的,下面我們就來看看這些魔術方法的實例。
魔術方法:
__construct(),类的构造函数 __destruct(),类的析构函数 __call(),在对象中调用一个不可访问方法时调用 __callStatic(),用静态方式中调用一个不可访问方法时调用 __get(),获得一个类的成员变量时调用 __set(),设置一个类的成员变量时调用 __isset(),当对不可访问属性调用isset()或empty()时调用 __unset(),当对不可访问属性调用unset()时被调用。 __sleep(),执行serialize()时,先会调用这个函数 __wakeup(),执行unserialize()时,先会调用这个函数 __toString(),类被当成字符串时的回应方法 __invoke(),调用函数的方式调用一个对象时的回应方法 __set_state(),调用var_export()导出类时,此静态方法会被调用。 __clone(),当对象复制完成时调用
#__construct()和__destruct()
建構子與析構函數應該不陌生,他們在物件創建和消亡時被呼叫。例如我們需要打開一個文件,在物件創建時打開,物件消亡時關閉
#<?php class FileRead { protected $handle = NULL; function __construct(){ $this->handle = fopen(...); } function __destruct(){ fclose($this->handle); } } ?>
這兩個方法在繼承時可以擴展,例如:
<?php class TmpFileRead extends FileRead { function __construct(){ parent::__construct(); } function __destruct(){ parent::__destruct(); } } ?>
__call()和__callStatic()
在物件中呼叫一個不可存取方法時會呼叫這兩個方法,後者為靜態方法。這兩個方法我們在可變方法(Variable functions)呼叫中可能會用到。
<?php class MethodTest { public function __call ($name, $arguments) { echo "Calling object method '$name' ". implode(', ', $arguments). "\n"; } public static function __callStatic ($name, $arguments) { echo "Calling static method '$name' ". implode(', ', $arguments). "\n"; } } $obj = new MethodTest; $obj->runTest('in object context'); MethodTest::runTest('in static context'); ?>
__get(),__set(),
#__get屬性是當存取物件中的屬性不存在或非公有屬性的時候自動載入__get方法,參數只有一個name值,就是存取物件中
屬性的名字。
__set是當給物件中一個屬性賦值的時候如果該屬性不存在或非公有屬性的時候就會自動載入__set方法。參數有兩個,參數1是存取物件中不可被呼叫屬性的名字,參數2是將要給賦值所傳的參數,可以是數組,也可以是字串
都具有公共可見性,非靜態,舉個小栗子方便理解:
<?php /** * 清晰的认识__get() __set() */ class Example { //公有的属性 public $public = 'pub' ; //受保护的 - 子类中该属性可用 protected $protected = 'pro'; //私有的 - 只能此类使用此属性 private $private = 'pri'; //当访问对象中的属性不存在或者非公有属性的时候自动加载__get()方法 public function __get($name){ return '调用__get()方法:'.$name; } //当给对象的一个属性赋值的时候如果该属性不存在或者是非公有属性则自动加载__set()方法 public function __set($name,$value){ echo "\nname:".$name.',value:'.$value."\n"; } } $example = new Example; echo '<pre class="brush:php;toolbar:false">'; echo $example->public."\n"; echo $example->protected."\n"; echo $example->private."\n"; echo $example->other."\n"; echo '<hr>'; $example->public = 'lic'; //这个赋值成功所有没有显示 $example->protected = 'tec'; $example->private = 'vat'; $example->other = 'er'; echo '<br/>';
echo '列印public 屬性:'.$example->public;
__isset()和__unset()
__isset()在物件中呼叫屬性或非類別中呼叫屬性使用isset()方法的時候如果沒有或非公有屬性
就會自動執行isset()的方法
__unset()在物件中調用屬性或非類別中調用屬性使用unset()方法如果沒有或非公有屬性就會
#自動執行__unset()的調用,可以將無法呼叫的成員屬性刪除,如果沒有在類別中加入此方法就無法刪除
物件中的任何私有成員,
一起舉個小栗子先:
<?php /** * 针对类中的魔术方法 __isset() 和 __unset() 的例子 */ class Example { public $public; protected $protected; private $private; public function __construct(){ $this->public = 'pub'; $this->protected = 'pro'; $this->private = 'pri'; } public function __isset($var){ echo '这里通过__isset()方法查看属性名为 '.$var."\n"; } public function __unset($var){ echo '这里通过__unset()方法要销毁属性名为 '.$var."\n"; } } $exa = new Example; echo '<pre class="brush:php;toolbar:false">'; var_dump(isset($exa->public)); echo "\n"; var_dump(isset($exa->protected)); echo "\n"; var_dump(isset($exa->private)); echo "\n"; var_dump(isset($exa->noVar)); echo "\n"; echo '<hr/>'; unset($exa->public); var_dump($exa); echo "\n"; unset($exa->protected); echo "\n"; unset($exa->private); echo "\n"; unset($exa->noVar); echo "\n";
當我們在執行serialize()和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(); } } ?>
__toString()
物件當成字串時的回應方法。例如使用echo $obj;來輸出一個物件
<?php // Declare a simple class class TestClass { public function __toString() { return 'this is a object'; } } $class = new TestClass(); echo $class; ?>
這個方法只能回傳字串,而且不可以在這個方法中拋出異常,否則會出現致命錯誤。
__invoke()
呼叫函數的方式呼叫一個物件時的回應方法。如下
<?php class CallableClass { function __invoke() { echo 'this is a object'; } } $obj = new CallableClass; var_dump(is_callable($obj)); ?>
__set_state()
當呼叫var_export()導出類別時,此靜態方法會被呼叫。
<?php class A { public $var1; public $var2; public static function __set_state ($an_array) { $obj = new A; $obj->var1 = $an_array['var1']; $obj->var2 = $an_array['var2']; return $obj; } } $a = new A; $a->var1 = 5; $a->var2 = 'foo'; var_dump(var_export($a)); ?>
__clone()
當物件複製完成時呼叫。例如在設計模式詳解及PHP實作:單例模式一文中提到的單例模式實作方式,利用這個函數來防止物件被複製。
<?php public class Singleton { private static $_instance = NULL; // 私有构造方法 private function __construct() {} public static function getInstance() { if (is_null(self::$_instance)) { self::$_instance = new Singleton(); } return self::$_instance; } // 防止克隆实例 public function __clone(){ die('Clone is not allowed.' . E_USER_ERROR); } } ?>
魔術常數(Magic constants)
PHP中的常數大部分都是不變的,但是有8個常數會隨著他們所在程式碼位置的變化而變化,這8個常數稱為魔術常數。
__LINE__,檔案中目前的行號
__FILE__,檔案的完整路徑和檔案名稱
__DIR__,檔案所在的目錄
__FUNCTION__,函數名稱
__CLASS__,類別的名稱
__TRAIT__,Trait的名字
__METHOD__,類別的方法名稱
__NAMESPACE__,目前命名空間的名稱
這些魔術常數常常被用來取得目前環境資訊或記錄日誌。
相關建議:
以上是php中魔術方法是什麼? php魔術方法的使用總結(程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!