天天看點

《php面向對象》 第16課:魔術方法之autoload

在封裝類時,可以使用很多魔術方法。

PHP中把以兩個下劃線__開頭的方法稱為魔術方法(Magic methods),

前面課程中我們學習的構造方法__construct,析構方法 __destruct,就是其中的兩個魔術方法。

以下是PHP所有的魔術方法,我們了解一下。

魔術方法包括:

  • __construct(),類的構造函數
  • __destruct(),類的析構函數
  • __call(),在對象中調用一個不可通路方法時調用
  • __callStatic(),用靜态方式中調用一個不可通路方法時調用
  • __get(),獲得一個類的成員變量時調用
  • __set(),設定一個類的成員變量時調用
  • __isset(),當對不可通路屬性調用isset()或empty()時調用
  • __unset(),當對不可通路屬性調用unset()時被調用。
  • __sleep(),執行serialize()時,先會調用這個函數
  • __wakeup(),執行unserialize()時,先會調用這個函數
  • __toString(),類被當成字元串時的回應方法
  • __invoke(),調用函數的方式調用一個對象時的回應方法
  • __set_state(),調用var_export()導出類時,此靜态方法會被調用。
  • __clone(),當對象複制完成時調用
  • __autoload(),嘗試加載未定義的類
  • __debugInfo(),列印所需調試資訊

今天 我們要講的是:__autoload(),為什麼要學它呢?因為它與後面我們要學習的MVC有關,現在我們就簡單學習一下。

__autoload(),這是一個自動加載函數,在PHP5中,當我們執行個體化一個未定義的類時,就會觸發此函數。看下面例子:

我們建立了一個test.php檔案

<?php

//自動執行的函數,必須有一個參數
function __autoload($class){

    echo $class;
}

//因為我們沒有包含student類檔案,當使用student類時,會自動執行__autoload函數
$stu = new Student();
$stu->say();
           

運作結果如下

《php面向對象》 第16課:魔術方法之autoload

其中的Student 是__autoload 函數輸出的

下面的錯誤提示,是因為我們沒有包含student類檔案而造成的。

隻要我們在__autoload函數,完成加載類檔案,就能保證程式的正常執行。

接下來,我們建立一個student.php檔案

<?php
class Student
{
    public function say()
    {
        echo 'hello';
    }
}
           

然後,我們改寫test.php檔案中的__autoload 函數

<?php

//自動執行的函數,必須有一個參數
function __autoload($class){
    //$class 是傳遞過來的類名
    //建構類檔案的路徑
    $file = strtolower($class) . '.php';

    //判斷檔案是否存在
    if(is_file($file)){
        //如果存在此檔案,則包括該檔案
        require_once $file;
    }else{
        //如果沒有此檔案,則終止程式
        die('類檔案未找到');
    }

}

//因為我們沒有包含student類檔案,當使用student類時,會自動執行__autoload函數
$stu = new Student();
$stu->say();
           

執行結果如下:

《php面向對象》 第16課:魔術方法之autoload

很明顯示,程式能正常執行了。

autoload機制可以使得PHP程式有可能在使用類時才自動包含類檔案,而不是一開始就将所有的類檔案include進來,這種機制也稱為lazy loading。

如果,我們的student類有自己的命名空間,會發生什麼情況呢?

student.php檔案

<?php
namespace model;//此處添加了命名空間
class Student
{
    public function say()
    {
        echo 'hello';
    }
}
           

test.php檔案

<?php
use model\Student;

//自動執行的函數,必須有一個參數
function __autoload($class){
    //$class 是傳遞過來的類名
    //建構類檔案的路徑
    $file = strtolower($class) . '.php';

    //判斷檔案是否存在
    if(is_file($file)){
        //如果存在此檔案,則包括該檔案
        require_once $file;
    }else{
        //如果沒有此檔案,則終止程式
        die('類檔案未找到');
    }

}

//因為我們沒有包含student類檔案,當使用student類時,會自動執行__autoload函數
$stu = new Student();
$stu->say();
           

運作結果如下

《php面向對象》 第16課:魔術方法之autoload

給類添加了命名空間後,為什麼找不到類檔案呢?

因為此時的_autoload函數接收到的參數值是:model\Student

此時建構的檔案路徑是:model\Student.php

是以當test.php和student.php在同一個目錄時,當然找不到類檔案了。

 我們需要把student.php放到下一級目錄model中

test.php和student.php之間的目錄關系如下:

《php面向對象》 第16課:魔術方法之autoload

同時,我們改寫__autoload中的部分代碼

<?php
use model\Student;

//自動執行的函數,必須有一個參數
function __autoload($class){
    //$class 是傳遞過來的類名
    //建構類檔案的路徑
    //注意__DIR__ 和轉義字元 \ 的使用
    $file =__DIR__ ."\\". strtolower($class) . '.php';

    //判斷檔案是否存在
    if(is_file($file)){
        //如果存在此檔案,則包括該檔案
        require_once $file;
    }else{
        //如果沒有此檔案,則終止程式
        die('類檔案未找到');
    }

}

//因為我們沒有包含student類檔案,當使用student類時,會自動執行__autoload函數
$stu = new Student();
$stu->say();
           

按照以上步驟改造完成後,程式又能正常執行了。

總結:

__autoload函數 :主要的功能就是構造需要加載的類檔案的路徑,然後包括包含類檔案。這一切都是當程式找不到類檔案時自動執行的。