搜尋
首頁後端開發php教程PHP中類別自動載入的方式

PHP中類別自動載入的方式

May 02, 2018 pm 03:20 PM
php載入方式

這篇文章主要介紹了關於PHP中類自動加載的方式,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

  最近在學習composer,發現從接觸PHP到現在已經遇到了三種關於PHP中類別的自動載入方式,其中包括PHP自帶的類別的自動載入方式、PHP的第三方的依賴管理工具composer的載入方式以及PHP的Yaf框架下的自動加載方式。本篇部落格主要是針對PHP5自備的載入方式進行詳細介紹,composer和Yaf下類的自動載入將在接下來的時間裡分兩篇和大家一起學習。

      1.手動載入方式

  像C和C 等語言,在PHP中需要使用另一個文件中的相關的類別、方法時,可以使用include、include_once、require或require_once將所使用的檔案包含進工程裡面。其中,四者的區別如下。

  • include將套用一個文件,如果文件不存在,則給予一個提示,跳過繼續執行;

  • include_once也是套用一個文件,但是只會套用一次,如果文件不存在,則繼續執行;

  • require表示套用一個文件,如果文件不存在,則中斷程式的執行;

  • require_once也是套用一個文件,且只會套用一次,如果文件不存在,則中斷程式的執行;

  以上四種方式是需要什麼文件的時候,手動在程式當中包含進文件。這在專案的規模比較小的時候,是可以的;但是隨著專案規模的擴大,要透過手動的方式載入每個檔案所需的類別簡直是一場噩夢。

  為了省事,在載入的時候可以透過set_include_path()設定載入的路徑,同樣也可以透過get_include_path()取得載入的路徑。關於set_include_path()和get_include_path(),我也是剛接觸,這裡只對set_include_path()作簡要的介紹,以後遇到問題再加以補充。

  首先,set_include_path()是在腳本中動態的對php.ini中的include_path進行動態的修改,而這個include_path就是對include和require(下文中如果不進行特別的說明,include代表include和include_once,require代表require和require_once)的路徑進行設置,或者說是預先定義。假如,我們在一個main.php檔案中需要使用projname/home/lib/mylib/test資料夾下的a.php、b.php、c.php......,如果沒有設定包含的路徑的話,那麼寫成如下的形式:

< ? php

        include("projname/home/lib/mylib/test/a.php");
        include("projname/home/lib/mylib/test/b.php");
        include("projname/home/lib/mylib/test/c.php");
	  ......

  這樣,每個include都需要包含絕對路徑,顯得很麻煩。如果在需要被包含的檔案之前加上set_include_path(“projname/home/lib/mylib/test”),那麼就可以寫成如下所示的形式:

< ? php

    set_include_path("projname/home/lib/mylib/test");
    include("a.php");
    include("b.php");
    include("c.php");
    ......

  相比於第一種費時費力的寫法,第二種明顯省去了很多的時間,但是仍然是要將每個文件包含進來,只是簡化了包含的路徑而已。當然,上面所說的情況是所需要的文件都存在於一個資料夾中,如果文件存在於不同的資料夾中,那麼可以添加多個條的set_include_path()語句,此時如果include或require中的文件包含的檔案名稱在多個目錄下出現,那麼只會包含最先出現在set_include_path目錄中的文件;如果所有的set_include_path指定的資料夾中都沒有對應的文件,而文件名稱恰好出現在目前的資料夾中,則直接包含目前目錄下的對應的檔案。

  get_include_path()函数只适用于获取当前的包含路径。 

  2._autoload和spl_autoload_register()自动加载方式

  为了将双手从类的加载方式中解放出来,在PHP5及以后的版本中提供了一个自动加载的机制---autoload。Autoload可以使类在确实被需要的情况下才会被加载进来,也就是所谓的lazy loading,而不是一开始就include或者require所有的类文件。其中PHP提供的自动加载机制又分为两种---__autoload()以及spl_autoload_register()。

  1). __autoload机制

  在PHP5中运行程序的过程中,如果发现某一个类并没有被包含进来,那么就会运行__autoload自动加载机制,将所需要的类加载进来。其写法如下:

< ? php

	public function  __autoload($classname) {
		$fileName = $classname."php";
		if (file_exist($fileName)) {
			require_once("$fileName");
		} else {
			echo $fileName." doesn&#39;t exist!"
		}
	}

  根据这个程序写法,我们可以得到如下的结论:保证自动加载机制的的原则就是要使得类名和文件名具有一种对应关系,类名+后缀构成了这个类所在的文件的名字。如果这个文件确实存在,那么就根据$fileName将该类加载进来。如果文件不存在,则提示用户,文件不存在。总的来说自动加载机制包括三个步骤:

  • 根据类名确定文件名,也就是确定一种类名和文件名之间的统一对应规则;

  • 根据文件名在磁盘上找到相应的对应文件(例子中是最简单的情况,就是类与调用他们的PHP文件都在同一个目录下);如果不在同一个目录下,那么可以使用set_include_path()指定要加载的路径;

  • 将磁盘文件加载到文件系统中,这一步只是用一般的include和require包含相应的类文件;

  __autoload()实现类的自动加载的原则就是:类名和文件名之间具有一种统一的对应关系,这是在一个系统中实现__autoload的关键所在。但是一个系统可能是有不同的人员所开发,如果在开发之前没有约定统一的标准,则可能存在不同的对应规则,导致需要在__autoload()中实现多种加载规则,那么可能导致__autoload()函数非常的臃肿。为了解决这个这个问题,PHP还提供了一个自动加载机制---spl_autoload_register().

  2). spl_autoload_register()机制

  SPL是Standard PHP Library(标准PHP库)的缩写,是PHP5引入的一个扩展库。SPL autoload是通过将函数指针autoload_func指向自动装载函数实现的。SPL具有两个不同的自动装载函数,分别是spl_autoload和spl_autoload_call,通过将autoload_fun指向这两个不同的加载函数地址可以实现不同的自动加载机制。

  • spl_autoload

  spl_autoload是SPL实现的默认的自动加载函数,是一个可以接受两个参数的函数。其中第一个函数为$class_name,表示要加载的类名;第二个参数是$file_extension为可选参数,表示类文件的扩展名。$file_extension中可以指定多个扩展名,扩展名之间用分号隔开即可,不指定扩展名,则使用默认的扩展名.inc或者.php。spl_autoload首先将$class_name变为小写,然后在所有的include_path中搜索$ class_name.inc或者$class_name.php文件。如果找到对应的文件,就加载对应的类。其实可以手动的使用spl_autoload("xxxx",".php")来实现xxxx类的加载。这其实和require/include差不多,但是,spl_autoload相对来说灵活一点,因为可以指定多个扩展名。

  前面说到,spl_autoload_register中包含的函数指针autoload_func用于指定要使用的加载函数。那么,我们必须将对应的函数地址赋值给autoload_func,spl_autoload_register()正实现了给函数指针autoload_func赋值的功能。如果spl_autoload_register()函数中不含有任何的参数,则默认是将spl_autoload()赋值给autoload_func.

  • spl_autoload_call 

  SPL模块的内部其实还存在着一个autoload_functions,其本质上是一个哈希表,或者为了直观的理解,我们将其想像成一个容器,里面的各个元素都是指向加载函数的指针。spl_autoload_call的实现机制其实也比较简单,按照一定的顺序遍历这个容器,执行里面的函数指针指向的加载函数,每执行一个指针之后都会检查所需要的类是否已经完成加载。如果完成了加载,则退出。否则继续接着向下执行。如果执行完所有的加载函数之后,所需要的类仍然没有完成加载,则spl_autoload_call()直接退出。这也就是说即使使用了autoload机制,也不一定能够完成类的加载,其关键在于看你如何创建你的自动加载函数。

  既然,存在一个autoload_functions,那么如何将创建的自动加载函数添加到其中呢?spl_autoload一样,同样使用spl_autoload_register()将加载函数注册到autoload_functions中。当然可以通过spl_autoload_unregister()函数将已经注册的函数从autoload_functions从哈希表中删除。

  这里需要说明的一点是spl_autoload_register实现自动加载的顺序。spl_autoload的自动加载顺序为:首先判断autoload_func是否为空,如果autoload_func为空,则查看是否定义了__autoload函数,如果没有定义,则返回,并报错;如果定义了__autoload()函数,则返回加载的结果。如果autoload_func不为空,直接执行autoload_func指针指向的函数,不会检查__autoload是否定义。也就是说优先使用spl_autoload_register()注册过的函数。

  根据以上介绍,如果autoload_func为非空是就不能自动执行__autoload()函数了。如果想在使用spl_autoload_register()函数的情况下,依然可以使用__autoload()函数,则可以将__autoload函数通过spl_autoload_register()添加到哈希表中,即,spl_autoload_register(__autoload())。下面的代码示例分别说明了如何注册普通的方法和类的静态公有方法。

  普通函数的注册方法。

<? php

	/**
	* @ 普通函数的调用方法,可以调用后缀名分别为.php和.class.php的类文件
	*/
	function loadFielEndOfPhp($classname) {
		$fileName = $classname.".php";
		if (file_exist($fileName)) {
			require_once("$fileName");
		} else {
			echo $fileName." doesn&#39;t exist!"
		}
	}

	function loadFielEndOfClassPhp($classname) {
		$fileName = $classname.".class.php";
		if (file_exist($fileName)) {
			require_once("$fileName");
		} else {
			echo $fileName." doesn&#39;t exist!"
		}
	spl_autoload_register("loadFielEndOfPhp"); 
	spl_autoload_register("loadFielEndOfClassPhp");

}

  类中静态的加载函数的注册方法。

<? php

	/**
	* @ 类中静态成员函数的调用方法,可调用后缀名为.php和.class.php的文件
	*/
    class test {
		public static function loadFielEndOfPhp($classname) {
			$fileName = $classname.".php";
			if (file_exist($fileName)) {
				require_once("$fileName");
			}
			else {
				echo $fileName." doesn&#39;t exist!"
			}
		}

		public static function loadFielEndOfClassPhp($classname) {
			$fileName = $classname.".class.php";
			if (file_exist($fileName)) {
				require_once("$fileName");
			}
			else {
				echo $fileName." doesn&#39;t exist!"
			}
	}
	
	spl_autoload_register(array("test","loadFielEndOfPhp")); 
	//spl_autoload_register("test::loadFielEndOfPhp");         //上一行的另一种写法,不是使用数组的形式完成注册;
	spl_autoload_register(array("test","loadFielEndOfClassPhp"));
	//spl_autoload_register("test::loadFielEndOfClassPhp");    //第三行的另一种写法,不是使用数组的形式完成注册;

}

相关推荐:

PHP中類別靜態呼叫和範圍解析運算元的差異

#PHP中類別自動載入實例解析

##PHP中類別的操作

以上是PHP中類別自動載入的方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
使用數據庫存儲會話的優點是什麼?使用數據庫存儲會話的優點是什麼?Apr 24, 2025 am 12:16 AM

使用數據庫存儲會話的主要優勢包括持久性、可擴展性和安全性。 1.持久性:即使服務器重啟,會話數據也能保持不變。 2.可擴展性:適用於分佈式系統,確保會話數據在多服務器間同步。 3.安全性:數據庫提供加密存儲,保護敏感信息。

您如何在PHP中實現自定義會話處理?您如何在PHP中實現自定義會話處理?Apr 24, 2025 am 12:16 AM

在PHP中實現自定義會話處理可以通過實現SessionHandlerInterface接口來完成。具體步驟包括:1)創建實現SessionHandlerInterface的類,如CustomSessionHandler;2)重寫接口中的方法(如open,close,read,write,destroy,gc)來定義會話數據的生命週期和存儲方式;3)在PHP腳本中註冊自定義會話處理器並啟動會話。這樣可以將數據存儲在MySQL、Redis等介質中,提升性能、安全性和可擴展性。

什麼是會話ID?什麼是會話ID?Apr 24, 2025 am 12:13 AM

SessionID是網絡應用程序中用來跟踪用戶會話狀態的機制。 1.它是一個隨機生成的字符串,用於在用戶與服務器之間的多次交互中保持用戶的身份信息。 2.服務器生成並通過cookie或URL參數發送給客戶端,幫助在用戶的多次請求中識別和關聯這些請求。 3.生成通常使用隨機算法保證唯一性和不可預測性。 4.在實際開發中,可以使用內存數據庫如Redis來存儲session數據,提升性能和安全性。

您如何在無狀態環境(例如API)中處理會議?您如何在無狀態環境(例如API)中處理會議?Apr 24, 2025 am 12:12 AM

在無狀態環境如API中管理會話可以通過使用JWT或cookies來實現。 1.JWT適合無狀態和可擴展性,但大數據時體積大。 2.Cookies更傳統且易實現,但需謹慎配置以確保安全性。

您如何防止與會議有關的跨站點腳本(XSS)攻擊?您如何防止與會議有關的跨站點腳本(XSS)攻擊?Apr 23, 2025 am 12:16 AM

要保護應用免受與會話相關的XSS攻擊,需採取以下措施:1.設置HttpOnly和Secure標誌保護會話cookie。 2.對所有用戶輸入進行輸出編碼。 3.實施內容安全策略(CSP)限制腳本來源。通過這些策略,可以有效防護會話相關的XSS攻擊,確保用戶數據安全。

您如何優化PHP會話性能?您如何優化PHP會話性能?Apr 23, 2025 am 12:13 AM

优化PHP会话性能的方法包括:1.延迟会话启动,2.使用数据库存储会话,3.压缩会话数据,4.管理会话生命周期,5.实现会话共享。这些策略能显著提升应用在高并发环境下的效率。

什麼是session.gc_maxlifetime配置設置?什麼是session.gc_maxlifetime配置設置?Apr 23, 2025 am 12:10 AM

theSession.gc_maxlifetimesettinginphpdeterminesthelifespanofsessiondata,setInSeconds.1)它'sconfiguredinphp.iniorviaini_set().2)abalanceisesneededeededeedeedeededto toavoidperformance andunununununexpectedLogOgouts.3)

您如何在PHP中配置會話名?您如何在PHP中配置會話名?Apr 23, 2025 am 12:08 AM

在PHP中,可以使用session_name()函數配置會話名稱。具體步驟如下:1.使用session_name()函數設置會話名稱,例如session_name("my_session")。 2.在設置會話名稱後,調用session_start()啟動會話。配置會話名稱可以避免多應用間的會話數據衝突,並增強安全性,但需注意會話名稱的唯一性、安全性、長度和設置時機。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具