国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PHP命名空間和自動加載類

姘存按 / 494人閱讀

摘要:在命名空間內部,所有的沒有根據導入規則轉換的限定名稱均會在其前面加上當前的命名空間名稱。為了引用全局命名空間中的全局類,必須使用完全限定名稱。實際上命名空間和自動加載類的結合就基本是通過路徑形式將命名空間路徑替換為實際路徑。

背景

最近有個朋友問我 PHP 命名空間是咋樣的,但是由于長期不做開發,筆者實際上也已經忘得差不多了,所以也回答不出來。只是記得和 Java 挺像的。事后重新查了一下 PHP 的官方文檔,并且和 Java 做對比,Java 的命名空間實際上來自于 JVM 本身的機制,JVM 是基于 class 字節碼文件加載類,由于類很容易出現重名的情況,換言之 class 字節碼文件也會出現重名情況,所以就需要使用目錄來管理不同的字節碼文件,而為了保證加載正常,所以就需要命名空間這種機制。當然,也可以說是由于命名空間的存在才有了目錄管理的方式。但是 PHP 和 Java 不一樣,PHP 是一種動態腳本語言,它的代碼分散在所有腳本中,當需要的時候才會使用 include 函數加載對應的文件,所以 PHP 的命名空間,實際上是基于 PHP 的自動加載類,自動加載類實現了才能保證 PHP 命名空間存在的意義。

命名空間概述

命名空間據筆者所知應該最早源于 C++ 語言,在 C++98 標準以后,為了保證各種命名不重合所推出的一種解決方案。現在的面向對象語言基本都有這種機制,當然除了命名空間以外,還有很多種方式,比如模塊化,不過實際上這些機制都是用來解決封裝問題的,所以筆者個人認為并無好壞之分。
先把 PHP 官方文檔代碼拉出來溜溜

非常容易理解的代碼,從上面的代碼中可以看到 PHP 定義的命名空間是怎么樣的,不過筆者個人認為其定義非常反人類,居然使用反斜杠來分隔命名空間路徑。不過有一點需要注意,名為 PHP 或 php 的命名空間,以及以這些名字開頭的命名空間(例如PHPClasses)被保留用作語言內核使用,而不應該在用戶空間的代碼中使用。

定義命名空間

PHP 命名空間功能只能在 PHP5.3.0 以上版本使用,對于一個命名空間,只有類、接口、函數和常量會被包含在命名空間中。

當然,也可以使用花括號來包含所有需要的內容,就像這樣。

不過這樣很容易造成縮進上的問題,所以筆者不推薦使用,并且一般情況下,一個文件包含一個類,所以也不需要花括號來分割命名空間范圍。

使用命名空間

對于命名空間路徑來說,存在著三種形式

非限定名稱,或者說不包含前綴的類名稱。例如 $a=new foo();foo::staticmethod();。如果當前命名空間是 currentnamespacefoo 將被解析為 currentnamespacefoo。如果使用 foo 的代碼是全局的,不包含在任何命名空間中的代碼,則 foo 會被解析為foo`。

限定名稱,或包含前綴的名稱,例如 $a = new subnamespacefoo();subnamespacefoo::staticmethod();。如果當前的命名空間是 currentnamespace,則 foo 會被解析為 currentnamespacesubnamespacefoo。如果使用 foo 的代碼是全局的,不包含在任何命名空間中的代碼,foo 會被解析為 subnamespacefoo

完全限定名稱,或包含了全局前綴操作符的名稱,例如, $a = new currentnamespacefoo();currentnamespacefoo::staticmethod();。在這種情況下,foo 總是被解析為代碼中的文字名 (literal name)currentnamespacefoo

由于 PHP 本身動態語言的特性,所以完全可以使用字符串動態訪問命名空間內的元素。

不過有一點需要注意,就是單雙引號之間的區別,單引號可以不需要處理 的轉譯處理,而雙引號就必須使用 等轉譯符號。
Java 語言使用 import 機制引入命名空間,由于 Java 可以指定到類名,所以 Java 最多只能導入到具體類,而 PHP 則可以指定到一個命名空間內的類、常量、方法等,并且支持命名空間別名。

名稱解析規則

首先就是前面講過的三種名稱類型,名稱解析遵循以下規則:

對完全限定名稱的函數,類和常量的調用在編譯時解析。例如 new AB 解析為類 AB。

所有的非限定名稱和限定名稱(非完全限定名稱)根據當前的導入規則在編譯時進行轉換。例如,如果命名空間 ABC 被導入為 C,那么對 CDe() 的調用就會被轉換為 ABCDe()。

在命名空間內部,所有的沒有根據導入規則轉換的限定名稱均會在其前面加上當前的命名空間名稱。例如,在命名空間 AB 內部調用 CDe(),則 CDe() 會被轉換為 ABCDe() 。

非限定類名根據當前的導入規則在編譯時轉換(用全名代替短的導入名稱)。例如,如果命名空間 ABC 導入為C,則 new C() 被轉換為 new ABC() 。

在命名空間內部(例如AB),對非限定名稱的函數調用是在運行時解析的。例如對函數 foo() 的調用是這樣解析的:

在當前命名空間中查找名為 ABfoo() 的函數

嘗試查找并調用 全局(global) 空間中的函數 foo()。

在命名空間(例如AB)內部對非限定名稱或限定名稱類(非完全限定名稱)的調用是在運行時解析的。下面是調用 new C() 及 new DE() 的解析過程:

new C()的解析:

在當前命名空間中查找ABC類。

嘗試自動裝載類ABC。

new DE()的解析:

在類名稱前面加上當前命名空間名稱變成:ABDE,然后查找該類。

嘗試自動裝載類 ABDE。

為了引用全局命名空間中的全局類,必須使用完全限定名稱 new C()。

從上面的規則來看,實際上 PHP 的導入規則和 Java 有點類似,但是卻有不一樣,主要是因為 Java 是完全面向對象的,而 PHP 本質上還只是一種基于對象的語言。

自動加載類

在早期 PHP 開發中,開發者最煩的就是一堆 include 函數包含了一大堆文件,而且早期時候 PHP 面向對象的概念確實太差了,因為 PHP 作為一種腳本語言,不存在程序入口,所以腳本順序化執行的誘惑力實在是很大,即使面向對象開發,但是缺少極佳的模塊劃分導入機制,代碼可以說很難有美感,最大的代表就是 Wordpress。如果有朋友看過這個典型項目,可以覺得非常痛苦,因為各種初始化、業務流程都分散在各個不同的文件中,使用 include 函數進行銜接,然后每次頁面渲染都是同樣的要走一趟流程。當然,這是 Wordpress 的歷史包袱,而在支持老版本 PHP 的情況下 Wordpress 代碼已經寫得足夠優化了。
在 PHP5 中就不需要這么麻煩了,因為可以定義一個 __autoload() 函數,當調用一個未定義的類的時候就會啟動此函數,從而在拋出錯誤之前做最后的補救,不過這個函數的本意已經被完全曲解使用了,現在都用來做自動加載。
注意,這個函數實際上已經不被推薦使用了,相反,現在應當使用 spl_autoload_register() 來注冊類的自動加載函數。

bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )

autoload_function 是需要注冊的自動裝載函數,如果此項為空,則會注冊 spl_autoload 函數,
throw 此參數設置了 autoload_function 無法成功注冊時, spl_autoload_register() 是否拋出異常。
prepend 如果是 true,spl_autoload_register() 會添加函數到隊列之首,而不是隊列尾部。
上面提到了 spl_autoload 函數,實際上注冊函數的規范就應當遵循此函數,函數聲明如下:

void spl_autoload ( string $class_name [, string $file_extensions ] )

由于這個函數默認實現是通過 C 語言,所以這里給出一個 PHP 語言的實現規范。

大致上就和這個是類似的。實際上命名空間和自動加載類的結合就基本是通過路徑形式

function __autoload(){
    $dir = "./libralies";
    set_include_path(get_include_path(). PATH_SEPARATOR. $dir);
    $class = str_replace("", "/", $class) . ".php"; 
    require_once($class);
}

將命名空間路徑替換為實際路徑。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/21491.html

相關文章

  • PHP自動加載功能原理解析

    摘要:前言在開始之前,歡迎關注我自己的博客這篇文章是對自動加載功能的一個總結,內容涉及的自動加載功能的命名空間的與標準等內容。要實現第一步,第二步的功能,必須在開發時約定類名與磁盤文件的映射方法,只有這樣我們才能根據類名找到它對應的磁盤文件。 前言 在開始之前,歡迎關注我自己的博客:www.leoyang90.cn 這篇文章是對PHP自動加載功能的一個總結,內容涉及PHP的自動加載功能、P...

    Imfan 評論0 收藏0
  • Composer的Autoload源碼實現——啟動與初始化

    摘要:任務是加載類的初始化頂級命名空間與文件路徑映射初始化和注冊。在實際情況下可能會出現這樣的情況。值得注意的是這個函數返回的是一個匿名函數,為什么呢原因就是類中的等等都是的。。。關于匿名函數的綁定功能。 前言 在開始之前,歡迎關注我自己的博客:www.leoyang90.cn 上一篇文章,我們討論了 PHP 的自動加載原理、PHP 的命名空間、PHP 的 PSR0 與 PSR4 標準,有...

    MarvinZhang 評論0 收藏0
  • ThinkPHP5.1 源碼淺析(二)自動加載機制

    摘要:如果遍歷后沒有找到,則加載失敗。在之后碰到了之后直接拿來用,提高系統自動加載的性能。這里我們就講完了注冊自動加載。使用自動加載我們在中定義了我們自動加載函數式方法。 繼 生命周期的第二篇,大家盡可放心,不會隨便鴿文章的 第一篇中,我們提到了入口腳本,也說了,里面注冊了自動加載的功能 本文默認你有自動加載和命名空間的基礎。如果沒有請 看此篇文章 php 類的自動加載與命名空間 自動加載...

    mudiyouyou 評論0 收藏0
  • Composer的Autoload源碼實現——注冊與運行

    前言 在開始之前,歡迎關注我自己的博客:www.leoyang90.cn上一篇 文章我們講到了 Composer 自動加載功能的啟動與初始化,經過啟動與初始化,自動加載核心類對象已經獲得了頂級命名空間與相應目錄的映射,換句話說,如果有命名空間 AppConsoleKernel,我們已經知道了 App 對應的目錄,接下來我們就要解決下面的就是 ConsoleKernel這一段。 注冊 我們先回顧...

    wanghui 評論0 收藏0
  • 自動加載命名空間

    摘要:不傳參數,直接調用,會默認調用來加載類,如果后面再調用有傳參數的,也會失效的如果使用了命名空間,那么會把路徑和類名一同帶過來的。 自動加載 兩種實現方式 1、__autoload(); 2、spl_autoload_register(); (主要使用) __autoload()現在很少使用,因為使用這種方式,在一個系統的實現中,假如需要使用很多其它的類庫,這些類庫可能是由...

    songjz 評論0 收藏0

發表評論

0條評論

姘存按

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<