php攔截器(魔術方法)


什么是PHP攔截器?

   英文名稱 “interceptor”,作用是 攔截 發送未定義的方法和屬性的消息。

    先看一段代碼,定義了一個School類,實例化一個對象$obj,獲取一個未定義的屬性teacher,會發生什么呢?

<?php
class School
{

}

$obj = new School;
var_dump($obj->teacher);

 

如果使用php命令行執行,可以看出,php報了一個未定義屬性的Notice, $obj->teacher值是空值,所以打印出NULL

[root@localhost php]# php538 interceptor.php 
PHP Notice:  Undefined property: School::$teacher in /usr/local/sina_mobile/apache/htdocs/php/interceptor.php on line 11
NULL

 

這里說明一下,php命令行執行和瀏覽器頁面執行不一定完全一樣,我們可以看下面截圖,web server是 apache執行同樣腳本時候,apache回告瀏覽器的是未帶php報出的Notice,返回給瀏覽器的是一個200 OK,這里面存在這php和web server的交互以及web server和瀏覽器的交互問題。

 

針對前面的代碼,我們想,如果訪問teacher的時候,teacher屬性不存在,我們可以攔截到對teacher的調用請求,並且做一些操作,那么這個就是php的攔截器,php攔截器提供了多種方法,這里__get方法就是訪問未定義的屬性時候被調用的。我們看下面代碼和結果

<?php

class School
{
    function __get($var)
    {
       echo $var; echo "\r\n"; 
       return "hello";
    }

    public $name = "Tom";

}

$obj = new School;
var_dump($obj->teacher);
var_dump($obj->name);

 

執行以下結果如下,說明一下,__get方法必須擁有一個參數,該參數就是調用的未定義的屬性名稱,函數會將return 結果賦值給該調用的未知屬性。

[root@localhost php]# php538 interceptor.php 
teacher
string(5) "hello"
string(3) "Tom"

 

php提供了哪些攔截器方法

 在有些文章中,把php攔截器一起稱未php魔術方法,這里我們把這些方法做個整理

序號 方法名 作用 實現版本
1 __get($property) 訪問未定義的屬性時候,調用該方法 >= PHP 5.3.0
2 __set($property, $value) 給未定義屬性設置值的時候,調用該方法 >= PHP 5.3.0
3 __isset($property) 對未定義屬性調用isset()時,調用該方法 >= PHP 5.1.0
4 __unset($property) 對未定義屬性調用unset()時,調用該方法 >= PHP 5.1.0
5 __call($property, $args_array) 調用未定義方法時,執行該方法 >= PHP 5.3.0
6 __autoload($classname) 請求類時,先執行該方法 >= PHP 5.3.0
7 __construct($args) 一個類中,只有一個構造函數,new 類的時候,構造函數優先被執行  
8 __destruct() 一個類中,只有一個析構函數,釋放類的時候,析構函數被執行  
9 __clone() 使用clone創建對象副本時候,該方法被調用 >= PHP 5.3.0
10 __tostring() __toString() 方法用於一個類被當成字符串時應怎樣回應 >= PHP 5.2.0
11 __sleep() serialize() 函數會檢查類中是否存在一個魔術方法 __sleep()。如果存在,該方法會先被調用,然后才執行序列化操作 >= PHP 5.3.0
12 __wakeup() unserialize() 會檢查是否存在一個 __wakeup() 方法 >= PHP 5.3.0
13 __set_state 調用 var_export() 導出類時,此靜態 方法會被調用。  >= PHP 5.3.0
14 __invoke 當嘗試以調用函數的方式調用一個對象時,__invoke() 方法會被自動調用。  >= PHP 5.3.0
15 __callstatic() 用靜態方式中調用一個不可訪問方法時,__callStatic() 會被調用  
16 __debugInfo() 使用var_dump()打印對象的時候,該方法被調用 >= PHP 5.6.0

 

詳細情況見 http://php.net/manual/zh/language.oop5.magic.php介紹

 

結論

 在這里,可以把上表中序號1-5的方法稱之為攔截器方法,后面稱之為魔術方法,魔術方法可以理解成是提供給php程序員對php標准函數的"重寫", 可以理解成zend虛擬機,在解析php腳本的時候,發現一些未定義的方法屬性,或者發現一些提供用戶重載的標准函數,如clone,serialize等時候,優先查看是否有需要自行的魔術方法。

 

參考文獻:

《深入PHP面向對象、模式與實踐》(第3版)/(美)Zandstra,M. 著,陳浩等譯. 北京:人民郵電出版社,2011.7 ISDN 978-7-115-25624-9

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM