在php中自動加載我們會使用到方法__autoload spl_autoload_register來實現,像我們有幾百個類時我們希望是希望使用__autoload來創建,然后直接創建類名就可以了,下面簡單的總結了一下自動加載類的用法,希望對各位有幫助.
在PHP5之前,各個PHP框架如果要實現類的自動加載,一般都是按照某種約定自己實現一個遍歷目錄,自動加載所有符合約定規則的文件的類或函數,當然,PHP5之前對面向對象的支持并不是太好,類的使用也沒有現在頻繁,在PHP5后,當加載PHP類時,如果類所在文件沒有被包含進來,或者類名出錯,Zend引擎會自動調用__autoload 函數,此函數需要用戶自己實現__autoload函數, 在PHP5.1.2版本后,可以使用spl_autoload_register函數自定義自動加載處理函數,當沒有調用此函數,默認情況下會使用SPL自定義的spl_autoload函數,看下面兩個例子:
1、__autoload示例:
- function __autoload($class_name) {
- echo '__autload class:', $class_name, '<br />';
- }
- new Demo();
以上的代碼在最后會輸出:__autload class:Demo。
2、spl_autoload_register示例:
- function classLoader($class_name) {
- echo 'SPL load class:', $class_name, '<br />';
- }
- spl_autoload_register('classLoader');
- new Demo();
以上的代碼在最后會輸出:SPL load class:Demo。
并在此之后報錯顯示:Fatal error: Class 'Demo' not found
以上的兩個示例表明:當類不存在時(即需要的類不在類符號表),Zend引擎會將再調用一次用戶定義的函數,如__autoload或spl_autoload_register注冊的函數,如果這兩個方法同時存在,那么程序會調用哪一個呢?還是說兩個都調用?看下面一個示例,你覺得會輸出什么呢?代碼如下:
- function __autoload($class_name) {
- echo '__autload class:', $class_name, '<br />';
- }
- function classLoader($class_name) {
- echo 'SPL load class:', $class_name, '<br />';
- }
- spl_autoload_register('classLoader');
- new Demo();
__set、__tostring等類的魔法方法的常量定義在源碼級別是一起的,可是它并不是專屬于某個類的魔法方法,它是所有的類共用的自動加載魔術方法,它將作為一個全局函數存在,那么Zend引擎是如何在類沒有找到時調用這個方法的呢?
不管是使用new關鍵字創建類的實例,還是使用implement實現接口,或者繼承某個類, 所有的這些操作都有可能調用__autoload函數,這幾個操作在源碼層都有一個共同點,它們在執行的時候都需要獲取類的信息(接口在本質上也是一個類),它們在最終都會調用 zend_fetch_class(Zend/zend_execute_API.c)函數,這個函數本身沒有多少內容,關鍵是它調用了zend_lookup_class_ex(Zend/zend_execute_API.c)函數,這個函數就是類的自動加載的真相所在.
在zend_lookup_class_ex函數中,我們看到程序會首先查詢類符號表,如果存在類直接返回,如果不存在,就會執行我們所說的自動加載了,這里針對__autoload函數和spl相關的函數都做了處理,并且以第一參數和第二參數傳遞給Zend引擎的函數調用函數zend_call_function.
在zend_call_function函數中,它會判斷第二參數是否存在函數,如果存在函數則只會調用第二個參數傳遞的函數(這里指SPL注冊的函數),如果第二個函數沒有值,則執行第一個參數傳遞過來的函數(這里指用戶定義的__autoload函數),到這里,我想前面提到的兩個方法同時存在的情況應該就有答案了,這也算是一篇基于的php教程了。
新聞熱點
疑難解答