天天看點

php 如何實作自動加載

什麼是自動加載

自動加載就是當我們在目前檔案中執行個體化一個不存在的類時,調用自動加載機制引入相應的類檔案。

注:自動加載有兩種方式(都是php内置的),一種是通過__autoload(),另一種是通過spl_autoload_register()。

二、通過__autoload() 實作自動加載

/data/www/test2/test2.php

<?php
 
class test2
{
 
    function aa()
    {
        echo 'this is function aa';
        echo "<br><br>";
    }
 
    static function bb()
    {
        echo 'this is function bb';
        echo "<br><br>";
    }
}      

/data/www/test3.php

<?php
 
//加載過程
//1、執行個體化test2類,由于目前檔案不存在test2類,是以會自動執行__autoload()方法,并自動将類名傳過去
//2、執行完__autoload()方法之後,會加載test2/test2.php檔案
//3、由于目前檔案已經通過__autoload()方式require進檔案test2.php了,是以也就可以調用test2.php中的方法了
 
$test = new test2();
$test->aa();//調用aa方法
test2::bb();//調用bb靜态類方法
 
function __autoload($class)
{
    echo '目前自動加載的類名為'.$class."<br><br>";//此時,$class的值就是test2
 
    include_once __DIR__.'/test2/'.$class.'.php';//相當于加載了test2/test2.php      

三、通過spl_autoload_register()實作自動加載【推薦的方式】

注:由于__autoload()自動加載方式已經逐漸被php官方廢棄了,是以這裡采用另一種方式spl_autoload_register來實作。

這裡,test2.php檔案和上面一樣,隻改變test3.php檔案。

/data/www/test3.php

<?php
 
//加載過程
//1、執行個體化test2類時,由于目前檔案并沒有test2類,是以php會自動調用spl_autoload_register自動加載機制
//2、調用spl_autoload_register,就會調用我們自己定義的autoload_test()方法
//3、進而引入了相應的test2.php類檔案
//4、引入了相應的類檔案之後,自然也就可以執行個體化類,并調用相應的方法了
 
spl_autoload_register(autoload_test);
 
$test = new test2();
$test->aa();//調用aa方法
test2::bb();//調用bb靜态類方法
 
 
/**
 * 用于實作自動加載
 * @param $class
 */
function autoload_test($class)
{
    echo '目前自動加載的類名為'.$class."<br><br>";//此時,$class的值就是test2
 
    include_once __DIR__.'/test2/'.$class.'.php';//相當于加載了test2/test2.php      

四、總結

spl_autoload_register()相比于__autoload()的優點在于:

(1)可以按需多次寫spl_autoload_register注冊加載函數,加載順序按誰先注冊誰先調用。__aotuload由于是全局函數隻能定義一次,不夠靈活。

比如下面,由于需要同時加載test2.php 以及 test4.class.php,__autoload就實作不了這個需求,而使用spl_autoload_register來實作就比較合适。

test4.class.php

<?php
 
class test4
{
 
    function dd()
    {
        echo "this is test4 function dd";
    }
 
}      

 test3.php

<?php
 
//加載過程
//1、執行個體化test2類時,由于目前檔案并沒有test2類,是以php會自動調用spl_autoload_register自動加載機制
//2、調用spl_autoload_register,就會調用我們自己定義的autoload_test()方法
//3、進而引入了相應的test2.php類檔案
//4、之後又執行個體化了test4類,test4類在目前檔案同樣沒有,這時php會自動調用spl_autoload_register自動加載機制
//4.1 首先調用第一個注冊自動加載函數spl_autoload_register(autoload_test),加載之後沒有找到test4類
//4.2 是以php會繼續調用第二個自動注冊函數spl_autoload_register(autoload_test4)
//4.3 這時,終于找到test4類了,也就不用繼續在往下找了
//5、引入了相應的類檔案之後,自然也就可以執行個體化類,并調用相應的方法了
 
spl_autoload_register(autoload_test);
spl_autoload_register(autoload_test4);
 
$test = new test2();
$test->aa();//調用aa方法
test2::bb();//調用bb靜态類方法
 
$test4 = new test4();
$test4->dd();
 
 
/**
 * 用于實作自動加載
 * @param $class
 */
function autoload_test($class)
{
    echo '目前自動加載的類名為'.$class."<br><br>";//此時,$class的值就是test2
    include_once __DIR__.'/test2/'.$class.'.php';//相當于加載了test2/test2.php
}
 
function autoload_test4($class)
{
    echo '目前自動加載的類名為'.$class."<br><br>";//此時,$class的值就是test4
    include_once __DIR__.'/'.$class.'.class.php';//相當于加載了test4.class.php      

(2)spl_autoload_register()可以被catch到錯誤,而__aotuload不能。

(3)spl_autoload_register注冊的加載函數可以按需被spl_autoload_unregister掉

還有,值得注意的是,如果對類檔案加入了命名空間,就必須保證正确的加載了類檔案的同時,還要通過use引入對應的命名空間。