下面我將對PHP所有的魔術方法進行介紹說明。其實下面的大多數方法,對於一個合格的PHP程式員來說,都是很熟悉的東西了。我在這裡作個總結,自己作個記錄學習,同時也給還未熟悉這些方法的同學們做個介紹。如有疏漏和錯誤,希望各位能指出。下面所提到的,大多數是PHP5所增加的魔術方法,少部分在PHP4裡就已經存在,少部分則是PHP5.1.0之後才出現的,這個在下面我將會提到。
__construct()和__destruct()
建構函式__construct()和解構函式__destruct(),這兩個不用我多說了吧,是個程式員都知道。__construct()會在執行個體建立的時候被調用,__destruct()在執行個體銷毀的時候被調用。需要注意的時候,即使你不顯式地調用unset去銷毀一個執行個體,它也會在指令碼運行結束的時候被銷毀。這兩個方法都可以傳遞0個或者多個參數。
<?phpclass o{ public function __construct() { echo 'building instance'; } public function __destruct() { echo 'destroy instance'; }}$i = new o;unset($i);//這句有無都不影響最後的輸出。__destruct()總是會被調用的//輸出//building instance//destroy instance?>
__get, __set, __isset, __unset
當對一個屬性進行操作的時候,如果該屬性不可獲得(不存在,或者當前環境不可調用該屬性,例如在子類中調用一個父類的private屬性),則調用以上方法的其中一個。調用什麼方法是依據對屬性所進行的操作。註:在php 5.0.*裡,這4個方法必須為public。
__get
觸發事件:調用屬性
參數 1 :所調用的屬性名稱
例子:
<?phpclass o{ protected function __get($var) { return 'No Member:'.$var; }}$i=new o();echo $i->name; // 輸出 No Member:name?>
<?phpclass o{ private $name='surfchen';//注意這裡的private protected function __get($var) { return 'No Member:'.$var; }}class child extends o{function test(){echo $this->name;}}$c=new child();echo $c->test(); // 輸出 No Member:name?>
__set
觸發事件:對一個屬性進行賦值
參數 1 :所調用的屬性名稱
參數 2 :所賦予的值
例子:
<?phpclass o{protected function __set($var,$val){echo 'setting '.$var.' to '.$val."/n";}}$c=new o();echo $c->name='wolfzeus'; /*輸出:setting name to wolfzeuswolfzeus*/?>
__isset
觸發事件:用isset檢測屬性是否存在
參數 1 :所調用的屬性名稱
例子:
<?phpclass o{protected function __isset($var){echo $var.' have not been set';}}$c=new o();isset($c->name); /*輸出:name have not been set*/?>
__unset
觸發事件:unset一個屬性(無論這個屬性是否存在)
參數 1 :所調用的屬性名稱
例子:
<?phpclass o{protected function __unset($var){echo $var.' is unset';}}$c=new o();unset($c->name); /*輸出:name is unset*/?>
__call($func,$para)
當嘗試調用一個對象的方法的時候,如果該方法不存在,則調用__call($func,$para)方法。這個方法必須有兩個參數,第一個為調用的方法名,第二個是一個被呼叫者法的參數數組。需要注意的是,當你在一個子類調用父類的private的方法,或者在執行個體裡調用類的非protect方法的時候,並不會調用__call(),這是__call和__get等屬性操作方法的一個不同點。
<?phpclass o{protected function __call($func,$para){echo 'No Method:'.$func."/n".'With Below Parameters:'."/n";print_r($para);}}$c=new o();echo $c->getNames('programmer','geek'); /*輸出:No Method:getNamesWith Below Parameters:Array( [0] => programmer [1] => geek)*/?>
__sleep(), __wakeup()
__sleep是當序列化(serialize)一個執行個體的時候被調用,__wakeup()則是在還原序列化(unserialize)的時候被調用。需要注意一點,就是__sleep()必須返回一個數組或者對象(一般返回的是$this),返回的值將會被用來做為序列化的值。如果不返回這個值,則序列化失敗。這也意味著還原序列化將不會觸發__wakeup事件。下面是一個可用的例子。
<?phpclass o{public $a='xx';public $b='55';function __sleep(){echo "I am sleepy/n";return $this;}function __wakeup(){echo "wake up!/n";}}$i = new o;$si = serialize($i);echo "sleeping now...../n";print_r(unserialize($si));?>
__toString()
當直接列印一個對象的時候,這個方法將會被調用。
例子:
<?phpclass o{private $name = 'surfchen';public function __toString(){return $this->name;}}$i = new o;echo 'name:',$i;//注意這裡串連name和變數$i的是逗號而不是句號?>
__set_state()
var_export可以把一個集合匯出為一串字串,這些字串是一些可執行檔PHP代碼。在php5.1.0的物件導向裡,引入了一個叫__set_state的靜態方法來使得var_export支援對象執行個體的匯出。當用var_export匯出一個執行個體的時候,所匯出字串裡,是調用這個靜態方法的代碼。這個方法有一個參數,為包含所匯出的執行個體的所有成員屬性的一個數組。有點抽象,看下面的例子吧。
<?phpclass o{public $skill='php';public static function __set_state($arr){foreach ($arr as $k => $v) {$obj->$k = $v;} return $obj;}}$i = new o;$i->age = 21;eval('$b = '.var_export($i,true).';');//這裡的true表示var_export返回所匯出的字串,而不是把它列印出來。print_r($b);/*輸出:stdClass Object( [skill] => php [age] => 21)*/?>
__clone()
在php5裡,對象間的賦值總是以地址引用來傳遞的。例如下面這個例子,將會輸出66,而不是55.
<?phpclass o{public $age = 55;}$i = new o;$i2 = $i;$i->age = 66;echo $i2->age;?>
如果要以實際值來傳遞,則需要用到clone關鍵詞。
<?phpclass o{public $age = 55;}$i = new o;$i2 = clone $i;$i->age = 66;echo $i2->age;//輸出55?>
但是,這裡clone的只是$i這個執行個體。如果$i的某個成員屬性也是個執行個體,那麼這個成員屬性還是會以引用方法被傳遞到$i2的。例如下面這個例子:
<?phpclass o{public $age = 55;public $sub = null;}class o2{public $p=1;}$i = new o;$i->sub=new o2;$i2 = clone $i;$i->sub->p=5;echo $i2->sub->p;?>
最後輸出的是5,而不是1。也就是說,$i和$i2雖然不是指向的雖然不是同一個執行個體,但是它們的成員屬性$sub卻是指向同一個執行個體。這時候,我們必須藉助__clone這個方法來對$sub進行複製。在o類裡,加入__clone()方法。如下:
<?phpclass o{public $age = 55;public $sub = null;public function __clone(){$this->sub=clone $this->sub;}}//......?>
這樣,在echo $i2->sub->p;的時候,輸出的就是傳遞時候的值1了。
__autoload()
當建立一個執行個體化的時候,如果對應的類不存在,__autoload()將會被執行,這個函數有一個參數,為所要建立的執行個體對應的類名。在下面的例子裡,當建立一個test類的執行個體的時候,如果/home/surfchen/project/auto.php存在,則require這個檔案,否則列印一個Class test Not Found的錯誤,並中止當前指令碼。
<?phpfunction __autoload($class_name) {if ($class_name == 'test') {$class_file = '/home/surfchen/project/auto.php';}if (is_file($class_file)) {require_once $class_file;return true;}echo 'Class '.$class_name.' Not Found';exit();}$o=new test();echo $o->a;?> TrackBack Tag(s): php — By: SurfChen