在封裝類時,可以使用很多魔術方法。
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();
運作結果如下
其中的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();
執行結果如下:
很明顯示,程式能正常執行了。
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();
運作結果如下
給類添加了命名空間後,為什麼找不到類檔案呢?
因為此時的_autoload函數接收到的參數值是:model\Student
此時建構的檔案路徑是:model\Student.php
是以當test.php和student.php在同一個目錄時,當然找不到類檔案了。
我們需要把student.php放到下一級目錄model中
test.php和student.php之間的目錄關系如下:
同時,我們改寫__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函數 :主要的功能就是構造需要加載的類檔案的路徑,然後包括包含類檔案。這一切都是當程式找不到類檔案時自動執行的。