PHP最先讀取套件的方法php
初學PHP時,最先會面對的問題之一就是require與include差別何在?
require_once與include_once又是什麼?
弄懂這些問題之後,若是不使用framework,直接開發,便常出現類似這樣的code:web
// whatever.php // 這檔案须要用到幾個類別 require 'xxx_class.php'; require 'yyy_class.php'; require 'zzz_class.php'; // ...
然後在其余檔案會出現:函数
// another.php // 這檔案须要用到幾個類別 require 'yyy_class.php'; require 'zzz_class.php'; // ...
這樣的結果,會產生至少兩個問題:
1. 許多檔案用到同樣幾個class,於是在不一样地方都须要載入一次。
2. 當類別多了起來,會顯得很亂、忘記載入時還會出現error。ui
那麼,不如試試一種懶惰的做法?
寫一個php,負責載入全部類別:code
// load_everything.php require 'xxx_class.php'; require 'yyy_class.php'; require 'zzz_class.php'; require 'aaa_class.php'; require 'bbb_class.php'; require 'ccc_class.php';
然後在其余檔案都載入這支檔案便可:io
require 'load_everything.php'
結果新問題又來了:當類別不少的時候,隨便一個web page都會載入一堆code,吃爆記憶體,怎麼辦呢?function
__autoloadclass
為了解決這個問題,PHP 5開始提供__autoload這種俗稱「magic method」的函式。
當你要使用的類別PHP找不到時,它會將類別名稱當成字串丟進這個函式,在PHP噴error投降以前,作最後的嘗試:test
// autoload.php function __autoload($classname) { if ($classname === 'xxx.php'){ $filename = "./". $classname .".php"; include_once($filename); } else if ($classname === 'yyy.php'){ $filename = "./other_library/". $classname .".php"; include_once($filename); } else if ($classname === 'zzz.php'){ $filename = "./my_library/". $classname .".php"; include_once($filename); } // blah }
也因為PHP這種「投降前最後一次嘗試」的行為,有時會讓沒注意到的人困惑「奇怪个人code怎麼跑得動?我根本沒有require啊..」,因此被稱為「magic method」。
如此一來,問題彷佛解決了?
惋惜還是有小缺點..,就是這個__autoload函式內容會變得很巨大。以上面的例子來說,一下會去根目錄找、一下會去other_library資料夾、一下會去my_library資料夾尋找。在整理檔案的時候,顯得有些混亂。require
spl_autoload_register
於是PHP從5.1.2開始,多提供了一個函式。
能够多寫幾個autoload函式,然後註冊起來,效果跟直接使用__autoload相同。
現在能够針對不一样用途的類別,分批autoload了。
spl_autoload_register('my_library_loader'); spl_autoload_register('other_library_loader'); spl_autoload_register('basic_loader'); function my_library_loader($classname) { $filename = "./my_library/". $classname .".php"; include_once($filename); } function other_library_loader($classname) { $filename = "./other_library/". $classname .".php"; include_once($filename); } function basic_loader($classname) { $filename = "./". $classname .".php"; include_once($filename); }
每個loader內容能够作不少變化。能够多寫判斷式讓它更智慧、能够進行字串處理…。
自動載入類別的問題終於解決了…。
使用spl_autoload_register注册了自定义的处理器以后,便不会再调用__autoload这个默认的处理器了。这样作的有点在于:__autoload是一个函数,它只能被定义一次,使用spl_autoload_register能够把须要在__autoload这一个加载器里作的事拆分到多个加载器中去分类管理,而且当php须要动态加载类时,spl_autoload_register会按注册顺序依次调用这些加载器来寻找并加载相应的类文件。
另外,注册到spl_autoload_register里的处理器方法还能够是类的静态方法:
<? class test { public static function loadprint( $class ) { $file = $class . '.class.php'; if (is_file($file)) { require_once($file); } } } spl_autoload_register( array('test','loadprint') ); //另外一种写法:spl_autoload_register( "test::loadprint" ); $obj = new PRINTIT(); $obj->doPrint(); ?>