程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 【PHP】__autoload()魔術方法與spl_autoload_register,splregisterautoload

【PHP】__autoload()魔術方法與spl_autoload_register,splregisterautoload

編輯:關於PHP編程

【PHP】__autoload()魔術方法與spl_autoload_register,splregisterautoload


參考鏈接:

1、spl_autoload_register與autoload的區別詳解

2、php.net 自動加載類

 

很多開發者寫面向對象的應用程序時對每個類的定義建立一個 PHP 源文件。一個很大的煩惱是不得不在每個腳本開頭寫一個長長的包含文件列表(每個類一個文件)。

在 PHP 5 中,不再需要這樣了。可以定義一個 __autoload() 函數,它會在試圖使用尚未被定義的類時自動調用。通過調用此函數,腳本引擎在 PHP 出錯失敗前有了最後一個機會加載所需的類。

 

簡單的引入例子:

先新建一個類文件MyClass.class.php:

<?php

class MyClass
{
    public function __construct()
    {
        echo "This is MyClass's construct";
    }

}

 

再在同目錄下新建任意名字的php文件:

<?php

function __autoload($cls){
    var_dump($cls);
    require './'.$cls.".class.php";
}

$o1 = new MyClass();
// 這裡不會再執行__autoload了,因為這個類已經require進來了。只有在當前文件中找不到該類的時候才會調用__autoload函數
$o2 = new MyClass();

這裡將require的內容放在了__autoload()中,如果沒有定義這個函數,會報一個致命錯誤(Fatal),提示找不到MyClass類。

而定義了這個魔術方法會在new一個對象 且 在當前代碼中找不到這個類定義的時候(滿足以上2個條件),__autoload()函數被傳入一個類名參數,並執行函數代碼段。

所以,在函數中執行了var_dump("MyClass");和require './MyClass.class.php';

 

結果如下:

string(7) "MyClass" This is MyClass's constructThis is MyClass's construct

這裡輸出了一次var_dump的內容和兩次構造函數echo的內容。可以證明,當require進來之後,再次new MyClass這個類,並不會再次調用__autoload()函數。

 

autoload有缺點:不能重復定義(PHP語言的特點),導致如果要進行團隊開發的時候很不方便,容易出現沖突。

於是PHP 5.1.2之後有一個autoload注冊函數spl_autoload_register,以下是此函數的一些說明:

將函數注冊到SPL __autoload函數隊列中。如果該隊列中的函數尚未激活,則激活它們。

如果需要多條 autoload 函數,spl_autoload_register() 滿足了此類需求。 它實際上創建了 autoload 函數的隊列,按定義時的順序逐個執行。相比之下, __autoload() 只可以定義一次。

 

在PHP 5.3引入了命名空間之後,此函數的參數有多種形式:

spl_autoload_register('my_autoloader');    // my_autoloader是一個函數名

spl_autoload_register(array('Loader', 'loadClass'));  // 表示類內的靜態方法,Loader::loadClass

// 或者,自 PHP 5.3.0 起可以使用一個匿名函數
spl_autoload_register(function ($class) {
    include 'classes/' . $class . '.class.php';
});

spl_autoload_register(__NAMESPACE__ .'\Foo::test'); // 自 PHP 5.3.0 起,可以使用命名空間的形式

 

這個函數只需要在new對象之前調用即可。

 

以下是一個例子(測試以上4種形式):

<?php

// namespace Atl;   // 加了這句話報錯了!

function my_autoloader($cls){
    echo "<br/>$cls - my_autoloader <br/>";
    require_once './MyClass1.class.php';
}

class Loader{

    public static function loadClass($cls){
        echo "<br/>$cls - Loader::loadClass <br/>";
        require_once './MyClass2.class.php';
    }

    public static function nspClass($cls){
        echo "<br/>$cls - Loader::nspClass <br/>";
        require_once './MyClass3.class.php';
    }

}

spl_autoload_register('my_autoloader');

$o1 = new MyClass1();

spl_autoload_register(array('Loader', 'loadClass'));

$o2 = new MyClass2();

// 版本檢測
if(version_compare(PHP_VERSION, '5.3.0', '<'))  die("以下的兩個測試需要PHP 5.3及以上");

spl_autoload_register(__NAMESPACE__ .'\Loader::nspClass');
$o3 = new MyClass3();

spl_autoload_register(function ($cls) {
    echo "<br/>$cls - anonymous function <br/>";
    require_once './MyClass4.class.php';
});

$o4 = new MyClass4();

 

輸出的結果如下(注意到查找的先後順序與注冊順序相同):

MyClass1 - my_autoloader 
This is MyClass1's construct
MyClass2 - my_autoloader 

MyClass2 - Loader::loadClass 
This is MyClass2's construct
MyClass3 - my_autoloader 

MyClass3 - Loader::loadClass 

MyClass3 - Loader::nspClass 
This is MyClass3's construct
MyClass4 - my_autoloader 

MyClass4 - Loader::loadClass 

MyClass4 - Loader::nspClass 

MyClass4 - anonymous function 
This is MyClass4's construct

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved