include 和 require 是php中引入檔案的兩個基本方法。在小規模開發中直接使用 include 和 require 沒喲什麼不妥,但在大型專案中會造成大量的 include 和 require 堆積。這樣的**既不優雅,執行效率也很低,而且維護起來也相當困難。
為了解決這個問題,部分框架會給出乙個引入檔案的配置清單,在物件初始化的時候把需要的檔案引入。
但這只是讓**變得更簡潔了一些,引入的效果仍然是差強人意。php5 之後,隨著 php 物件導向支援的完善,__autoload 函式才真正使得自動載入成為可能。
* include 和 require 功能是一樣的,它們的不同在於 include 出錯時只會產生警告,而 require 會丟擲錯誤終止指令碼。
* include_once 和 include 唯一的區別在於 include_once 會檢查檔案是否已經引入,如果是則不會重複引入。
1、自動載入__autoload(廢棄)
實現自動載入最簡單的方式就是使用 __autoload 魔術方法。當需要使用的類沒有被引入時,這個函式會在php報錯前被觸發,未定義的類名會被當作引數傳入。至於函式具體的邏輯,這需要使用者自己去實現。
首先建立乙個 autoload.php 來做乙個簡單的測試:
// 類未定義時,系統自動呼叫function __autoload($class)new helloworld();
/** * 輸出 helloworld 與報錯資訊
* fatal error: class 'helloworld' not found
*/
通過這個簡單的例子可以發現,在類的例項化過程中,系統所做的工作大致是這樣的:
/* 模擬系統例項化過程 */function instance($class)// 檢視 autoload 函式是否被使用者定義if (function_exists('__autoload'))
// 再次檢查類是否存在if (class_exists($class, false)) else
}
明白了 __autoload 函式的工作原理之後,那就讓我們來用它去實現自動載入。
首先建立乙個類檔案(建議檔名與類名一致),**如下:
class [classname]}
(我這裡建立了乙個 helloworld 類用作演示)接下來我們就要定義 __autoload 的具體邏輯,使它能夠實現自動載入:
function __autoload($class)}new helloworld();
/** * 輸出
*/
2、spl_autoload_register(推薦)
接下來讓我們要在含有命名空間的情況下去實現自動載入。這裡我們使用 spl_autoload_register() 函式來實現,這需要你的 php 版本號大於 5.12。
spl_autoload_register 函式的功能就是把傳入的函式(引數可以為**函式或函式名稱形式)註冊到 spl __autoload 函式佇列中,並移除系統預設的 __autoload() 函式。
一旦呼叫 spl_autoload_register() 函式,當呼叫未定義類時,系統就會按順序呼叫註冊到 spl_autoload_register() 函式的所有函式,而不是自動呼叫 __autoload() 函式。
注意:例項化乙個類時,需要先引用這個類檔案,才能被正確例項化成物件。
<?php//用法一:自動捕捉到類名//
spl_autoload_register([$this,'my_autoloader']); //my_autoloader是乙個類中的方法時
spl_autoload_register('my_autoloader'); //
my_autoloader是乙個函式時
function my_autoloader($class)
//用法二:自 php 5.3.0 起可以使用乙個匿名函式
spl_autoload_register(function ($class) );
?>
這裡我們使用了乙個陣列去儲存類名與檔案路徑的關係,這樣當類名傳入時,自動載入器就知道該引入哪個檔案去載入這個類了。但是一旦檔案多起來的話,對映陣列會變得很長,這樣的話維護起來會相當麻煩。如果命名能遵守統一的約定,就可以讓自動載入器自動解析判斷類檔案所在的路徑。接下來要介紹的psr-4 就是一種被廣泛採用的約定方式。
3、psr-4規範(推薦)
*****命名空間和檔名的對應關係*****
\頂級命名空間\子命名空間\類名 <*****==> \檔案基目錄\相對路徑\檔名
psr-4 規範中必須要有乙個頂級命名空間,它的意義在於表示某乙個特殊的目錄(檔案基目錄)。
子命名空間代表的是類檔案相對於檔案基目錄的這一段路徑(相對路徑),類名則與檔名保持一致(注意大小寫的區別)。/*
頂級命名空間路徑對映
*/$vendor_map = array(
/*解析類名為檔案路徑
*///
substr(string,start,length)擷取字元並返回
//strpos() 函式查詢字串在另一字串中第一次出現的位置。
$vendor = substr($class, 0, strpos($class, '\\')); //
$vendor_dir = $vendor_map[$vendor]; //
檔案基目錄[c:\baidu]
// 相對路徑[/view/news] 。dirname返回路徑的目錄部分。strlen獲取字串長度
$rel_path = dirname(substr($class, strlen($vendor
)));
//basename() 函式返回路徑中的檔名部分。
$file_name = basename($class) . '.php'; //
檔名[index.php]/*
輸出檔案所在路徑
*///
directory_separator相容的目錄分隔符
echo
$vendor_dir . $rel_path . directory_separator . $file_name;
通過這個 demo 可以看出限定類名轉換為路徑的過程。那麼現在就讓我們用規範的物件導向方式去實現自動載入器吧。
演示:例項化未引用的類,會自動將_類名 + 命名空間_轉化成絕對路徑,再次嘗試引用。
class index
}接著我們在建立乙個載入類(不需要命名空間),它處於 \ 目錄中:
classloader
} /**
* 解析檔案路徑
*/private
static
function findfile($class
)
/**
* 引入檔案
*/private
static
function includefile($file
)
}}
最後,將 loader 類中的 autoload 註冊到 spl_autoload_register 函式中:
include 'loader.php'; //引入載入器
spl_autoload_register('loader::autoload'); //
註冊自動載入
例項化未引用的類/*
* * 輸出:
*/
示例中的**其實就是 thinkphp 自動載入器原始碼的精簡版,它是 thinkphp 5 能實現惰性載入的關鍵。
至此,自動載入的原理已經全部講完了,如果有興趣深入了解的話,可以參考下面的 thinkphp 原始碼。
php 載入 php自動載入方式
本篇文章介紹的內容是關於php自動載入方式,現在分享給大家,有需要的朋友可以參考一下這篇文章的內容 php載入檔案方式 1 include,include once,requice,requice one常規載入 2 autoload 3 spl autoload register 常規載入方式 假...
php自動載入
很多開發者寫物件導向的應用程式時對每個類的定義建立乙個 php 原始檔。乙個很大的煩惱是不得不在每個指令碼 每個類乙個檔案 開頭寫乙個長長的包含檔案列表。在 php 5 中,不再需要這樣了。可以定義乙個 autoload 函式,它會在試圖使用尚未被定義的類時自動呼叫。通過呼叫此函式,指令碼引擎在 p...
php自動載入
php自動載方法有兩種.第一種方案用 autoload,這個函式較簡單,也較弱.但有一問題沒有解決,就是在include前判斷檔案是否存在的問題.1 2 3 4 5 6 7 8 9 10 11 12 13 set include path aa path separator get include ...