PHP之十六個魔法函數詳解


PHP中把以兩個下划線__開頭的方法稱為魔術方法(Magic methods),這些方法在PHP中充當了舉足輕重的作用。 魔術方法包括:

  1. __construct(),類的構造函數
  2. __destruct(),類的析構函數
  3. __call(),在對象中調用一個不可訪問方法時調用
  4. __callStatic(),用靜態方式中調用一個不可訪問方法時調用
  5. __get(),獲得一個類的成員變量時調用
  6. __set(),設置一個類的成員變量時調用
  7. __isset(),當對不可訪問屬性調用isset()或empty()時調用
  8. __unset(),當對不可訪問屬性調用unset()時被調用。
  9. __sleep(),執行serialize()時,先會調用這個函數

__wakeup(),執行unserialize()時,先會調用這個函數

  1. __toString(),類被當成字符串時的回應方法
  2. __invoke(),調用函數的方式調用一個對象時的回應方法
  3. __set_state(),調用var_export()導出類時,此靜態方法會被調用。
  4. __clone(),當對象復制完成時調用
  5. __autoload(),嘗試加載未定義的類
  6. __debugInfo(),打印所需調試信息

一、__construct(),類的構造函數。

php中構造方法是對象創建完成后第一個被對象自動調用的方法。在每個類中都有一個構造方法,如果沒有顯示地聲明它,那么類中都會默認存在一個沒有參數且內容為空的構造方法。

1、構造方法的作用

通常構造方法被用來執行一些有用的初始化任務,如對成員屬性在創建對象時賦予初始值。

2、構造方法在類中的聲明格式

function __construct([參數列表]){方法體}

3、在類中聲明構造方法的注意事項

在同一個類中只能聲明一個構造方法,原因是php不支持構造函數重載

構造方法名是以兩個下划線開始的__construct()

二、__destruct(),類的析構函數

析構方法允許在銷毀一個類之前執行的一些操作或完成一些功能,比如說關閉文件、釋放結果集等。(析構函數不能帶有任何參數)

三、__call(),在對象中調用一個不可訪問方法時調用。

該方法有倆個參數,第一個參數$function_name會自動接受不存在的方法名,第二個$arguments則以數組的方式接受不存在方法的多個參數。

1、__call()方法的格式:

function __call(string $function_name,array $arguments){方法體}

2、__call方法的作用:

為了避免當調用的方法不存在時產生錯誤,而意外的導致程序終止,可以使用__call()方法來避免。該方法在調用的方法不存在時會自動調用,程序仍會繼續執行下去。

四、__callStatic(),用靜態方式中調用一個不可訪問方法時調用

此方法與上面所說的__call()功能除了__callStatic()是為靜態方法准備的之外,其他都是一樣的。

php中調用靜態函數的方法是:$person1::eat();

五、__get(),獲得一個類的成員變量時調用

在php面向對象編程中,類的成員屬性被設定為private后,如果我們試圖在外面調用它則會出現“不能訪問某個私有屬性”的錯誤。那么為了解決這個問題,我們可以使用魔法方法__get()。

魔術方法__get()的作用:在程序運行過程中,通過它可以在對象的外部獲取私有成員屬性的值。

六、__set(),設置一個類的成員變量時調用

如果沒有__set()函數,對象的實例不能改變私有屬性的值,只能改變共有屬性的值。

__set()的作用:__set($property,$value)方法用來設置私有屬性,給一個未定義的屬性賦值時,此方法會被觸發,傳遞的參數是被設置的屬性名和值。

七、__isset(),當對不可訪問屬性調用isset()或empty()時調用。

isset函數是測定變量是否設定用的函數,傳入一個變量作為參數,如果傳入的變量存在則返回true,否則返回false

如果在一個對象外面使用isset()這個函數去測定對象里面的成員是否被設定可不可以用它?

分兩種情況,如果對象里面成員是公有的,我們就可以使用這個函數來測定成員屬性,如果是私有的成員屬性,這個函數就不起作用了,原因就是因為私有的被封裝了,在外部不可見。那么我們就不可以在對象外部使用isset()函數來測定私有成員屬性是否被設定了。當在類外部使用isset()函數來測定對象里的私有成員是否被設定時,就會自動調用類里面的__isset()方法來幫助我們完成這樣的操作。

__isset()的作用:當對不可訪問屬性調用isset()或empty()時,__isset()會被調用。

當成員變量時公共的時,可以直接使用isset()函數。而成員變量是私有的時,使用isset函數之前,會先調用__isset()函數。

八、__unset(),當對不可訪問屬性調用unset()時被調用

看這個方法之前呢,我們也先來看一下 unset() 函數,unset()這個函數的作用是刪除指定的變量且傳回true,參數為要刪除的變量。

那么如果在一個對象外部去刪除對象內部的成員屬性用unset()函數可以嗎?

這里自然也是分兩種情況:

1、 如果一個對象里面的成員屬性是公有的,就可以使用這個函數在對象外面刪除對象的公有屬性。

2、 如果對象的成員屬性是私有的,我使用這個函數就沒有權限去刪除。

雖然有以上兩種情況,但我想說的是同樣如果你在一個對象里面加上__unset()這個方法,就可以在對象的外部去刪除對象的私有成員屬性了。在對象里面加上了__unset()這個方法之后,在對象外部使用“unset()”函數刪除對象內部的私有成員屬性時,對象會自動調用__unset()函數來幫我們刪除對象內部的私有成員屬性。

九、__sleep(),執行serialize()時,先會調用這個函數

如果沒有__sleep()方法,php將保存所有屬性。

程序運行時, serialize() 檢查類中是否有 __sleep() ,如果有,則該函數將在任何序列化之前運行. 該函數必須返回一個需要進行序列化保存的成員屬性數組,並且只序列化該函數返回的這些成員屬性. 該函數有兩個作用: 第一. 在序列化之前,關閉對象可能具有的任何數據庫連接等. 第二. 指定對象中需要被序列化的成員屬性,如果某個屬性比較大而不需要儲存下來,可以不把它寫進__sleep()要返回的數組中,這樣該屬性就不會被序列化

十、__wakeup(),執行unserialize()時,先會調用這個函數

unserialize() 函數會檢測是否存在 __wakeup() 函數, 如果存在會先調用 __wakeup(), 預先准備對象數據. 在用 unserialize()時需要注意的一個問題: 在一個PHP頁面中要 unserialize() 一個對象,需要該頁面包含該對象的類的定義.也就是,如果序列化了 page1.php 中類 A 的對象 $a, 要在 page2.php 中將其反序列化重建類 A 的對象 $a, 則 page2.php 中必須要出現類 A 的定義. 這可以這樣實現,將類 A 的定義放在一個包含文件中,並在 page1.php 和 page2.php 都包含此文件. 所以強烈建議在所有的頁面中都包括這些注冊的對象的類的定義, 即使並不是在所有的頁面中都用到了這些類. 如果沒有這樣做, 一個對象被反序列化了但卻沒有其類的定義,它將失去與之關聯的類並成為 stdClass 的一個對象而完全沒有任何可用的函數。

__wakeup() 方法經常用在反序列化操作中, 例如重新建立數據庫連接,或其他的初始化工作。

十一、__toString(),類被當成字符串時的回應方法

作用:__toString()方法用於一個類被當成字符串時應怎樣回應。

注意:此方法必須返回一個字符串,否則會報錯

警告:不能在__toString()方法中拋出異常。這么做會導致致命錯誤。

輸出一個對象的時候會調用__tostring

十二、__invoke(),調用函數的方式調用一個對象時的回應方法

作用:當嘗試以調用函數的方式調用一個對象時,__invoke()函數會被調用。

注意:本特性只在PHP 5.3.0及以上的版本有效。

當然,如果你執意要將對象當函數方法使用,會得到下面結果:

Fatal error: Function name must be a string in D:\phpStudy\WWW\test\index.php on line 18

十三、__set_state(),調用var_export()導出類時,此靜態方法會被調用。。

作用:自PHP 5.1.0起,當調用var_export()導出類時,此靜態方法會被自動調用。

參數:本函數的唯一參數就是一個數組。

十四、__clone(),當對象復制完成時調用

在多數情況下,我們並不需要完全復制一個對象來獲得其中屬性。但有一個情況下確實需要:如果你有一個GTK窗口對象,該對象持有窗口相關資源。你可能會想復制一個新的窗口,保持所有屬性與原來的窗口相同,但必須是一個新對象(因為如果不是新對象,那么一個窗口中的改變就會影響到另一個窗口)。還有一種情況:如果對象A中保存着對象B的引用,當你復制對象A時,你想其中使用的對象不再是對象B而是對象B的一個副本,那么你必須得到對象A的一個副本。

十五、__autoload(),嘗試加載未定義的類

作用:你可以通過定義這個函數來啟用類的自動加載

十六、__debuginffo(),打印所需調試信息

注意:該方法在PHP 5.6.0及其以上版本可以使用。


免責聲明!

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



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