PHP高階特性 自動載入

2022-09-01 02:51:08 字數 4143 閱讀 6645

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

}接著我們在建立乙個載入類(不需要命名空間),它處於 \ 目錄中:

class

loader

}​ /**

* 解析檔案路徑

*/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 ...