1. 程式人生 > >php類檔案自動載入(autoload)

php類檔案自動載入(autoload)

php實現類檔案自動載入有兩種辦法:

  1. 魔術方法:__autoload();
  2. SPL標準庫提供的spl_autoload_register();

一、__autoload()

__autoload()是php中的一個魔術方法,在程式碼中當呼叫不存在的類時會自動呼叫該方法。

假如現在有以下兩個類檔案:

//Test1.php檔案
<?php
class Test1{
    static function test(){
        echo "test1";
    }
}
//Test2.php檔案
<?php
class Test2{
    static function
test(){
echo "test2"; } }

現在Test.php檔案中要用到 Test1.php 和 Test2.php 中的類:

//Test.php檔案
<?php
include "Test1.php";
include "Test2.php";

Test1::test();
Test2::test();

用 include 或require 的問題是當我要呼叫的類很多的時候,include 或 require也會很多,造成程式碼的冗雜,而且每次執行到 Test.php 檔案的時候都要載入這麼多檔案,有些檔案還不一定用到,那就浪費了很多記憶體,降低效率。再者是當你某個類檔案被刪掉了,你還得去修改 Test.php 檔案。

由於這些原因,我們用 __autoload() 去代替 include

//Test.php檔案
<?php
function __autoload($class){
    if(file_exists($class.".php")){
        require_once($class.".php");
    }else{
        die("檔案不存在!");
    }
}

Test1::test();
Test2::test();

__autoload() 魔術方法的作用是當你呼叫不存在的類時會被自動呼叫,在 Test.php檔案中我們呼叫 類Test1 和 類Test2,由於我們沒有顯式的引用類檔案,那麼系統就會自動呼叫 __autoload() 方法。

但是,到現在為止 __autoload() 方法基本上被廢棄了!為啥呢?因為:

1、最大的缺陷就是一個檔案中不允許有多個 __autoload()方法,想象一下,你的專案引用了別人的一個專案,你的專案中有一個 __autoload,別人的專案也有一個__autoload,這樣兩個__autoload就衝突了。解決的辦法就是修改__autoload成為一個,這無疑是非常繁瑣的。
2、假如你的專案中的類根據不同的用處放在不同的資料夾中 classes 和 core,然後Test.php檔案中要分別呼叫裡面對應的類,怎麼搞?這樣?

function __autoload($class){
    if(file_exists("classes/".$class.".php")){
        require_once("classes/".$class.".php");
    }else{
        die("檔案不存在!");
    }
}
function __autoload($class){
    if(file_exists("core/".$class.".php")){
        require_once("core/".$class.".php");
    }else{
        die("檔案不存在!");
    }
}

Test1::test();
Test2::test();

這樣做的話會出現致命錯誤,因為 __autoload()重複定義!(其實第1點的原因也是一樣)

為了解決這個問題,於是就有 spl_autoload_register()

二、spl_autoload_register()

好,到了這一步,我們先不說 spl_autoload_register(),既然不用__autoload(),那麼我們就自己定義負責類載入的函式:

function my_autoload1($class){
    if(file_exists("classes/".$class.".php")){
        require_once("classes/".$class.".php");
    }else{
        die("檔案不存在!");
    }
}
function my_autoload2($class){
    if(file_exists("core/".$class.".php")){
        require_once("core/".$class.".php");
    }else{
        die("檔案不存在!");
    }
}

//現在我們就可以載入類檔案啦
my_autoload1("Test1");
my_autoload2("Test2");

Test1::test();
Test2::test();

但是如上程式碼所示,直接呼叫我們的自定義類檔案載入函式跟 include 有啥區別嗎?這時 spl_autoload_register 就派上用場了。

顯然,創造一個負責類檔案載入函式不是為了讓我們直接呼叫它,而是讓PHP在需要類定義的時候為我們呼叫它。我們稱這種功能為“自動載入”。

要開啟“自動載入”功能,需要將載入函式註冊到PHP中:

spl_autoload_register("my_autoload1");

我們重新實現 Test.php:

//Test.php檔案
function my_autoload1($class){
    if(file_exists("classes/".$class.".php")){
        require_once("classes/".$class.".php");
    }else{
        die("檔案不存在!");
    }
}
function my_autoload2($class){
    if(file_exists("core/".$class.".php")){
        require_once("core/".$class.".php");
    }else{
        die("檔案不存在!");
    }
}

//將載入函式註冊到PHP中
spl_autoload_register("my_autoload1");
spl_autoload_register("my_autoload2");

Test1::test();
Test2::test();

這樣就是實現了PHP的類檔案自動載入功能。