亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > PHP > 正文

PHP命名空間和自動加載類

2024-05-04 23:44:39
字體:
來源:轉載
供稿:網友

PHP的命名空間(namespace)是php5.3之后才有的。這個概念在C#中已經很早就有了,php中的namespace其實和c#的概念是一樣的。

為什么php中要使用namespace?

假設如果不使用namespace,那么每個類在一個項目中的名字就必須是固定的。因為php在new的時候不管是調用autoload還是調用已加載過的類,都存在一個類名對應的文件。所以在沒有namespace的時候,我們會想各種命名規則來區分不同的類,比如project1_school1_class1_Student或者project2_school_class_Student。

引入namespace之后就可以將這個有效規避了,一個namespace就相當于對應一個文件路徑,查找這個類的時候,就會去對應的文件路徑查找類定義文件了。

背景

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

命名空間概述

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

<?phpnamespace my/name; // 參考 "定義命名空間" 小節class MyClass {}function myfunction() {}const MYCONST = 1;$a = new MyClass;$c = new /my/name/MyClass; // 參考 "全局空間" 小節$a = strlen('hi'); // 參考 "使用命名空間:后備全局函數/常量" 小節$d = namespace/MYCONST; // 參考 "namespace操作符和__NAMESPACE__常量” 小節$d = __NAMESPACE__ . '/MYCONST';echo constant($d); // 參考 "命名空間和動態語言特征" 小節?>

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

定義命名空間

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

<?phpnamespace MyProject;const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }?>

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

<?phpdeclare(encoding='UTF-8');namespace MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }}namespace { // 全局代碼session_start();$a = MyProject/connect();echo MyProject/Connection::start();}?>

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

使用命名空間

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

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

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

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

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

<?phpnamespace namespacename;class classname{function __construct(){echo __METHOD__,"/n";}}function funcname(){echo __FUNCTION__,"/n";}const constname = "namespaced";include 'example1.php';$a = 'classname';$obj = new $a; // prints classname::__construct$b = 'funcname';$b(); // prints funcnameecho constant('constname'), "/n"; // prints global/* note that if using double quotes, "//namespacename//classname" must be used */$a = '/namespacename/classname';$obj = new $a; // prints namespacename/classname::__construct$a = 'namespacename/classname';$obj = new $a; // also prints namespacename/classname::__construct$b = 'namespacename/funcname';$b(); // prints namespacename/funcname$b = '/namespacename/funcname';$b(); // also prints namespacename/funcnameecho constant('/namespacename/constname'), "/n"; // prints namespacedecho constant('namespacename/constname'), "/n"; // also prints namespaced?>

不過有一點需要注意,就是單雙引號之間的區別,單引號可以不需要處理 / 的轉譯處理,而雙引號就必須使用 // 等轉譯符號。

Java 語言使用 import 機制引入命名空間,由于 Java 可以指定到類名,所以 Java 最多只能導入到具體類,而 PHP 則可以指定到一個命名空間內的類、常量、方法等,并且支持命名空間別名。

<?phpnamespace foo;use My/Full/Classname as Another;// 下面的例子與 use My/Full/NSname as NSname 相同use My/Full/NSname;// 導入一個全局類use ArrayObject;// importing a function (PHP 5.6+)use function My/Full/functionName;// aliasing a function (PHP 5.6+)use function My/Full/functionName as func;// importing a constant (PHP 5.6+)use const My/Full/CONSTANT$obj = new namespace/Another; // 實例化 foo/Another 對象$obj = new Another; // 實例化 My/Full/Classname 對象NSname/subns/func(); // 調用函數 My/Full/NSname/subns/func$a = new ArrayObject(array(1)); // 實例化 ArrayObject 對象// 如果不使用 "use /ArrayObject" ,則實例化一個 foo/ArrayObject 對象func(); // calls function My/Full/functionNameecho CONSTANT; // echoes the value of My/Full/CONSTANT?>

名稱解析規則

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

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

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

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

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

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

在當前命名空間中查找名為 A/B/foo() 的函數

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

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

new C()的解析:

在當前命名空間中查找A/B/C類。

嘗試自動裝載類A/B/C。

new D/E()的解析:

在類名稱前面加上當前命名空間名稱變成:A/B/D/E,然后查找該類。

嘗試自動裝載類 A/B/D/E。

為了引用全局命名空間中的全局類,必須使用完全限定名稱 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 語言的實現規范。

<?php// Your custom class dirdefine('CLASS_DIR', 'class/')// Add your class dir to include pathset_include_path(get_include_path().PATH_SEPARATOR.CLASS_DIR);// You can use this trick to make autoloader look for commonly used "My.class.php" type filenamesspl_autoload_extensions('.class.php');// Use default autoload implementationspl_autoload_register();?>

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

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

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

以上內容是小編給大家介紹的PHP命名空間和自動加載類,希望對大家有所幫助!


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩成人激情影院| 久久久在线免费观看| 亚洲风情亚aⅴ在线发布| 亚洲xxxxx电影| 国产亚洲激情视频在线| 成人深夜直播免费观看| 精品国产一区二区三区久久狼黑人| 久久免费视频在线观看| 国产精品999999| 欧美日韩国产页| 国产精品黄色影片导航在线观看| 久久亚洲电影天堂| 亚洲欧美一区二区精品久久久| 精品亚洲国产成av人片传媒| 日韩在线视频免费观看| 久久精品成人欧美大片古装| 国产精品第二页| 久久久久久亚洲| 最近日韩中文字幕中文| 亚洲情综合五月天| 久久久久亚洲精品成人网小说| 精品久久中文字幕| 欧美亚洲国产日韩2020| 91精品在线看| 国产精品老女人精品视频| 亚洲精品成人av| 欧美极品少妇xxxxⅹ裸体艺术| 理论片在线不卡免费观看| 91精品中国老女人| 亚洲欧美日本精品| 国产成人综合久久| 亚洲美女久久久| 亚洲午夜国产成人av电影男同| 亚洲高清久久网| 92看片淫黄大片看国产片| 91精品在线一区| 欧美成人免费一级人片100| 91免费视频网站| 亚洲色图日韩av| 黄色一区二区三区| 欧美激情欧美激情在线五月| 国产精品99久久久久久久久| 欧洲日本亚洲国产区| 亚洲图片欧美午夜| 91在线无精精品一区二区| 国产一区二区久久精品| 精品国产乱码久久久久久虫虫漫画| 国产69精品久久久久9999| 欧美精品激情在线观看| 国产精品久久久久久av福利软件| 亚洲网址你懂得| 亚洲国产日韩欧美在线动漫| 日本午夜精品理论片a级appf发布| 欧美有码在线观看| 国语自产精品视频在免费| 日韩中文在线视频| 欲色天天网综合久久| 亚洲色图50p| 久久国产一区二区三区| 成人黄色短视频在线观看| 国产亚洲精品美女久久久久| 亚洲精品福利资源站| 91精品国产91久久久久久| 精品日本高清在线播放| 午夜精品福利电影| 国产成人综合一区二区三区| 在线丨暗呦小u女国产精品| 日韩毛片在线观看| 精品久久中文字幕久久av| 亚洲欧美综合v| 午夜欧美大片免费观看| 欧美成人免费在线观看| 一区二区福利视频| 国产女精品视频网站免费| 国语对白做受69| 78m国产成人精品视频| 69国产精品成人在线播放| 亚洲欧洲在线播放| 午夜精品久久久99热福利| 91久久综合亚洲鲁鲁五月天| 在线观看中文字幕亚洲| 91po在线观看91精品国产性色| 日韩精品黄色网| 日韩美女中文字幕| 亚洲精品资源美女情侣酒店| 成人午夜在线视频一区| 91久久精品美女| 国产精品成人品| 国产日韩欧美在线播放| 欧美激情一区二区三区高清视频| 9.1国产丝袜在线观看| 国产91对白在线播放| 亚洲人成网站免费播放| 一区二区三区高清国产| 另类图片亚洲另类| 免费91麻豆精品国产自产在线观看| 久久久久久有精品国产| 亚洲成人中文字幕| 久久久久免费精品国产| 亚洲影院色在线观看免费| 97成人精品视频在线观看| 日韩精品视频免费专区在线播放| 45www国产精品网站| 精品久久久久久| 精品色蜜蜜精品视频在线观看| 欧美日韩国产一区在线| 亚洲美女精品成人在线视频| 最近2019中文免费高清视频观看www99| 亚洲欧美另类国产| 成人黄色片在线| 欧美视频在线看| 日韩在线免费观看视频| 国产成人精品日本亚洲| 久久久久久久久网站| 成人疯狂猛交xxx| 超薄丝袜一区二区| 日韩风俗一区 二区| 97视频在线观看播放| 精品在线观看国产| 91精品国产自产在线| 久久久久亚洲精品成人网小说| 欧美视频在线视频| 亚洲护士老师的毛茸茸最新章节| 国语自产精品视频在线看抢先版图片| 国产小视频国产精品| 欧美性黄网官网| 亚洲性xxxx| 91夜夜未满十八勿入爽爽影院| 北条麻妃一区二区三区中文字幕| 欧美精品一区二区三区国产精品| 亚洲国产精品久久久久秋霞蜜臀| 成人免费在线视频网站| 色狠狠久久aa北条麻妃| 日韩在线视频一区| 日韩在线观看成人| 国产日韩在线精品av| 亚洲国产精品久久久久秋霞蜜臀| 亚洲国产精久久久久久久| 日韩电影免费观看在线| 欧美性一区二区三区| 久久久免费精品| 国产自产女人91一区在线观看| 欧美精品成人在线| 欧美性做爰毛片| 亚洲国产精品成人精品| 国产精品美女主播在线观看纯欲| 日韩大片免费观看视频播放| 狠狠躁夜夜躁久久躁别揉| 亚洲精品www| 日韩一二三在线视频播| 亚洲视频一区二区| 欧美日韩另类字幕中文| 亚洲欧美日韩天堂一区二区| 国产精品视频精品| 久久的精品视频| 国内外成人免费激情在线视频| 久久久久久久久久久久久久久久久久av| 亲爱的老师9免费观看全集电视剧| 亚洲香蕉在线观看| 国产精品欧美日韩| 98精品国产自产在线观看| 欧美亚洲国产日本| 国产欧美久久一区二区| 久久综合久久八八|