自PHP5後,官方大大豐富了對面向對象的支持,其中有個重要改變:引入了__autoload()函數,從此不再需要在php腳本的header寫一堆的require或include了,用PHP函數手冊中的話說:”它會在試圖使用尚未被定義的類時自動調用”。
這一機制大大減輕了開發人員的負擔,只要在架構初期考慮好了目錄結構和命名規範,在開發過程中,需要再爲代碼中要用到的類分別去require相應的文件,減少了大量代碼。
但這樣一來,也容易出現運行一個程序,某個類文件被include多次,例如有以下四個腳本:
- #file:include1.php
- include 'include2.php';
- //@todo something
- #file:include2.php
- //@todo something
- #file:script1.php
- include 'include2.php';
- //@todo something
- #file:script2.php
- include 'include1.php';
- include 'script1.php'
- //@todo something
當執行script1.php時, include ‘include2.php’; 這行代碼被執行了一次。而執行script2.php時,這行代碼被執行了兩次。
這裏只是一個簡單的例子,在實際的項目中,include2.php被include的次數可能更多。這樣反覆的include,是否會影響性能呢?爲此我寫了個腳本來測試。
- #file:simpleclass.php
- class simpleclass {
- public function __construct() {
- echo get_time() . "\r\n";
- }
- }
- #file:php_include.php
- for($i = 0;$i < $loop;$i++) {
- include_once "simpleclass.php";
- new simpleclass();
- }
當$loop值爲1時,腳本耗時約0.00018906593322754秒,當$loop爲1000時,腳本耗時約0.076701879501343秒。
如果我們用autoload實現呢?
- #file:php_autoload.php
- function __autoload($class_name) {
- include_once $class_name . '.php';
- }
- for($i = 0;$i < $loop;$i++) {
- new simpleclass();
- }
在這段代碼中,我定義了__autoload函數,幾乎一樣的腳本,當$loop爲1時,耗時0.0002131462097168秒,而當$loop爲1000時,耗時僅爲前面代碼的1/7,0.012391805648804秒。
但請注意看simpleclass的代碼,其中輸出了一行字符串,如果去掉這行輸出後再比較,會是什麼樣的結果呢?
在$loop同爲1000的情況下,前者耗時0.057836055755615秒,而使用了autoload後,僅僅0.00199294090271秒!效率相差近30倍!
從上面的測試可以看出,當文件僅僅被include一次,autoload會消耗稍微多一點的時間,但如果在文件被反覆include的情況下,使用autoload則能大大提高系統性能。
至於是否要使用autoload來解放程序員,這就仁者見仁,智者見智了。在我看來,條件允許的前提下,犧牲這一點性能(某些情況下,甚至可能是提升性能)更爲便捷的開發,是值得的。