目錄
PHP命名空间(Namespace)初探,命名空间namespace
基础
子空间
公共空间
名称术语
 
别名和导入
动态调用
字符串形式调用问题
总结
首頁 後端開發 php教程 PHP命名空间(Namespace)初探,命名空间namespace_PHP教程

PHP命名空间(Namespace)初探,命名空间namespace_PHP教程

Jul 12, 2016 am 08:51 AM
namespace

PHP命名空间(Namespace)初探,命名空间namespace

探完闭包[查看],再探命名空间。

对于命名空间,官方文档已经说得很详细[查看],我在这里做了一下实践和总结。

命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误。这种情况下只要避免命名重复就可以解决,最常见的一种做法是约定一个前缀。

例:项目中有两个模块:articlemessage board,它们各自有一个处理用户留言的类Comment之后我可能想要增加对所有用户留言的一些信息统计功能,比如说我想得到所有留言的数量。这时候调用它们Comment提供的方法是很好的做法,但是同时引入各自的Comment类显然是不行的,代码会出错,在另一个地方重写任何一个Comment也会降低维护性。那这时只能重构类名,我约定了一个命名规则,在类名前面加上模块名,像这样:Article_CommentMessageBoard_Comment

可以看到,名字变得很长,那意味着以后使用Comment的时候会写上更多的代码(至少字符多了)。并且,以后如果要对各个模块增加更多的一些整合功能,或者是互相调用,发生重名的时候就需要重构名字。当然在项目开始的时候就注意到这个问题,并规定命名规则就能很好的避免这个问题。另一个解决方法可以考虑使用命名空间。

 

注明:

本文提到的常量:PHP5.3开始const关键字可以用在类的外部。constdefine都是用来声明常量的(它们的区别不详述),但是在命名空间里,define的作用是全局的,而const则作用于当前空间。我在文中提到的常量是指使用const声明的常量。

 

 

基础

命名空间将代码划分出不同的空间(区域),每个空间的常量、函数、类(为了偷懒,我下边都将它们称为元素)的名字互不影响, 这个有点类似我们常常提到的‘封装’的概念。

创建一个命名空间需要使用namespace关键字,这样:

复制代码
<?<span>php

</span><span>//</span><span>创建一个名为'Article'的命名空间</span>
<span>namespace Article;

</span>?>
登入後複製
复制代码

要注意的是,当前脚本文件的第一个命名空间前面不能有任何代码,下面的写法都是错误的:

复制代码
<span>//</span><span>例一
//在脚本前面写了一些逻辑代码</span>

<?<span>php

</span><span>$path</span> = "/"<span>;

</span><span>class</span><span> Comment { }

namespace Article;

</span>?>
<br />

<span>//</span><span>例二
//在脚本前面输出了一些字符</span>

<html></html>
<?<span>php

namespace Article;

</span>?>
登入後複製
复制代码

为什么要说第一个命名空间呢?因为同一脚本文件中可以创建多个命名空间。

下面我创建了两个命名空间,顺便为这两个空间各自添加了一个Comment类元素:

复制代码
<?<span>php

</span><span>//</span><span>创建一个名为'Article'的命名空间</span>
<span>namespace Article;

</span><span>//</span><span>此Comment属于Article空间的元素</span>
<span>class</span><span> Comment { }



</span><span>//</span><span>创建一个名为'MessageBoard'的命名空间</span>
<span>namespace MessageBoard;

</span><span>//</span><span>此Comment属于MessageBoard空间的元素</span>
<span>class</span><span> Comment { }
</span>?>
登入後複製
复制代码

在不同空间之间不可以直接调用其它元素,需要使用命名空间的语法:

复制代码
<?<span>php

namespace Article;

</span><span>class</span><span> Comment { }



namespace MessageBoard;

</span><span>class</span><span> Comment { }

</span><span>//</span><span>调用当前空间(MessageBoard)的Comment类</span>
<span>$comment</span> = <span>new</span><span> Comment();

</span><span>//</span><span>调用Article空间的Comment类</span>
<span>$article_comment</span> = <span>new</span><span> \Article\Comment();

</span>?>
登入後複製
复制代码

可以看到,在MessageBoard空间中调用article空间里的Comment类时,使用了一种像文件路径的语法: \空间名\元素名

除了类之外,对函数和常量的用法是一样的,下面我为两个空间创建了新的元素,并在MessageBoard空间中输出了它们的值。

复制代码
<?<span>php

namespace Article;

</span><span>const</span> PATH = '/article'<span>;

</span><span>function</span><span> getCommentTotal() {
    </span><span>return</span> 100<span>;
}

</span><span>class</span><span> Comment { }




namespace MessageBoard;

</span><span>const</span> PATH = '/message_board'<span>;

</span><span>function</span><span> getCommentTotal() {
    </span><span>return</span> 300<span>;
}

</span><span>class</span><span> Comment { }

</span><span>//</span><span>调用当前空间的常量、函数和类</span>
<span>echo</span> PATH; <span>//</span><span>/message_board</span>
<span>echo</span> getCommentTotal(); <span>//</span><span>300</span>
<span>$comment</span> = <span>new</span><span> Comment();

</span><span>//</span><span>调用Article空间的常量、函数和类</span>
<span>echo</span> \Article\PATH; <span>//</span><span>/article</span>
<span>echo</span> \Article\getCommentTotal(); <span>//</span><span>100</span>
<span>$article_comment</span> = <span>new</span><span> \Article\Comment();

</span>?>
登入後複製
复制代码

然后我的确得到了Article空间的元素数据。

子空间

命名空间的调用语法像文件路径一样是有道理的,它允许我们自定义子空间来描述各个空间之间的关系。

抱歉我忘了说,articlemessage board这两个模块其实都是处于同一个blog项目内。如果用命名空间来表达它们的关系,是这样:

复制代码
<?<span>php

</span><span>//</span><span>我用这样的命名空间表示处于blog下的article模块</span>
<span>namespace Blog\Article;

</span><span>class</span><span> Comment { }



</span><span>//</span><span>我用这样的命名空间表示处于blog下的message board模块</span>
<span>namespace Blog\MessageBoard;

</span><span>class</span><span> Comment { }

</span><span>//</span><span>调用当前空间的类</span>
<span>$comment</span> = <span>new</span><span> Comment();

</span><span>//</span><span>调用Blog\Article空间的类</span>
<span>$article_comment</span> = <span>new</span><span> \Blog\Article\Comment();

</span>?>
登入後複製
复制代码

而且,子空间还可以定义很多层次,比如说 Blog\Article\Archives\Date

公共空间

我有一个common_inc.php脚本文件,里面有一些好用的函数和类:

复制代码
<?<span>php

</span><span>function</span><span> getIP() { }

</span><span>class</span><span> FilterXSS { }

</span>?>
登入後複製
复制代码

在一个命名空间里引入这个脚本,脚本里的元素不会归属到这个命名空间。如果这个脚本里没有定义其它命名空间,它的元素就始终处于公共空间中:

复制代码
<?<span>php

namespace Blog\Article;

</span><span>//</span><span>引入脚本文件</span>
<span>include</span> './common_inc.php'<span>;

</span><span>$filter_XSS</span> = <span>new</span> FilterXSS(); <span>//</span><span>出现致命错误:找不到Blog\Article\FilterXSS类</span>

<span>$filter_XSS</span> = <span>new</span> \FilterXSS(); <span>//</span><span>正确</span>


?>
登入後複製
复制代码

调用公共空间的方式是直接在元素名称前加 \ 就可以了,否则PHP解析器会认为我想调用当前空间下的元素。除了自定义的元素,还包括PHP自带的元素,都属于公共空间。

要提一下,其实公共空间的函数和常量不用加 \ 也可以正常调用(不明白PHP为什么要这样做),但是为了正确区分元素,还是建议调用函数的时候加上 \

名称术语

在说别名和导入之前,需要知道关于空间三种名称的术语,以及PHP是怎样解析它们的。官方文档说得非常好,我就直接拿来套了。

其实可以把这三种名称类比为文件名(例如 comment.php)、相对路径名(例如 ./article/comment.php)、绝对路径名(例如 /blog/article/comment.php),这样可能会更容易理解。

我用了几个示例来表示它们:

复制代码
<?<span>php

</span><span>//</span><span>创建空间Blog</span>
<span>namespace Blog;

</span><span>class</span><span> Comment { }

</span><span>//</span><span>非限定名称,表示当前Blog空间
//这个调用将被解析成 Blog\Comment();</span>
<span>$blog_comment</span> = <span>new</span><span> Comment();

</span><span>//</span><span>限定名称,表示相对于Blog空间
//这个调用将被解析成 Blog\Article\Comment();</span>
<span>$article_comment</span> = <span>new</span> Article\Comment(); <span>//类</span><span>前面没有反斜杆\

//完全限定名称,表示绝对于Blog空间
//这个调用将被解析成 Blog\Comment();</span>
<span>$article_comment</span> = <span>new</span> \Blog\Comment(); <span>//类</span><span>前面有反斜杆\

//完全限定名称,表示绝对于Blog空间
//这个调用将被解析成 Blog\Article\Comment();</span>
<span>$article_comment</span> = <span>new</span> \Blog\Article\Comment(); <span>//类</span><span>前面有反斜杆\



//创建Blog的子空间Article</span>
<span>namespace Blog\Article;

</span><span>class</span><span> Comment { }


</span>?>
登入後複製
复制代码

其实之前我就一直在使用非限定名称和完全限定名称,现在它们终于可以叫出它们的名称了。

别名和导入

别名和导入可以看作是调用命名空间元素的一种快捷方式。PHP并不支持导入函数或常量。

它们都是通过使用use操作符来实现:

复制代码
<?<span>php

namespace Blog\Article;

</span><span>class</span><span> Comment { }



</span><span>//创建一个BBS空间(我有打算开个论坛)</span>
<span>namespace BBS;

</span><span>//</span><span>导入一个命名空间</span>
<span>use</span><span> Blog\Article;
</span><span>//</span><span>导入命名空间后可使用限定名称调用元素</span>
<span>$article_comment</span> = <span>new</span><span> Article\Comment();

</span><span>//</span><span>为命名空间使用别名</span>
<span>use</span> Blog\Article <span>as</span><span> Arte;
</span><span>//</span><span>使用别名代替空间名</span>
<span>$article_comment</span> = <span>new</span><span> Arte\Comment();

</span><span>//</span><span>导入一个类</span>
<span>use</span><span> Blog\Article\Comment;
</span><span>//</span><span>导入类后可使用非限定名称调用元素</span>
<span>$article_comment</span> = <span>new</span><span> Comment();

</span><span>//</span><span>为类使用别名</span>
<span>use</span> Blog\Article\Comment <span>as</span><span> Comt;
</span><span>//</span><span>使用别名代替空间名</span>
<span>$article_comment</span> = <span>new</span><span> Comt();

</span>?>
登入後複製
复制代码

我注意到,如果导入元素的时候,当前空间有相同的名字元素将会怎样?显然结果会发生致命错误。

例:

复制代码
<?<span>php

namespace Blog\Article;

</span><span>class</span><span> Comment { }



namespace BBS;

</span><span>class</span><span> Comment { }

</span><span>Class</span><span> Comt { }


</span><span>//</span><span>导入一个类</span>
<span>use</span><span> Blog\Article\Comment;
</span><span>$article_comment</span> = <span>new</span> Comment(); <span>//</span><span>与当前空间的Comment发生冲突,程序产生致命错误

//为类使用别名</span>
<span>use</span> Blog\Article\Comment <span>as</span><span> Comt;
</span><span>$article_comment</span> = <span>new</span> Comt(); <span>//</span><span>与当前空间的Comt发生冲突,程序产生致命错误</span>

?>
登入後複製
复制代码

动态调用

PHP提供了namespace关键字和__NAMESPACE__魔法常量动态的访问元素,__NAMESPACE__可以通过组合字符串的形式来动态访问:

复制代码
<?<span>php

namespace Blog\Article;

</span><span>const</span> PATH = '/Blog/article'<span>;

</span><span>class</span><span> Comment { }


</span><span>//</span><span>namespace关键字表示当前空间</span>
<span>echo</span> namespace\PATH; <span>//</span><span>/Blog/article</span>
<span>$comment</span> = <span>new</span><span> namespace\Comment();

</span><span>//</span><span>魔法常量__NAMESPACE__的值是当前空间名称</span>
<span>echo</span> __NAMESPACE__; <span>//</span><span>Blog\Article
//可以组合成字符串并调用</span>
<span>$comment_class_name</span> = __NAMESPACE__ . '\Comment'<span>;
</span><span>$comment</span> = <span>new</span> <span>$comment_class_name</span><span>();

</span>?>
登入後複製
复制代码

字符串形式调用问题

上面的动态调用的例子中,我们看到了字符串形式的动态调用方式,如果要使用这种方式要注意两个问题。

1. 使用双引号的时候特殊字符可能被转义

复制代码
<?<span>php

namespace Blog\Article;

</span><span>class</span><span> name { }

</span><span>//</span><span>我是想调用Blog\Article\name</span>
<span>$class_name</span> = __NAMESPACE__ . "\name"; <span>//</span><span>但是\n将被转义为换行符</span>

<span>$name</span> = <span>new</span> <span>$class_name</span>(); <span>//</span><span>发生致命错误</span>

?>
登入後複製
复制代码

2. 不会认为是限定名称

PHP在编译脚本的时候就确定了元素所在的空间,以及导入的情况。而在解析脚本时字符串形式调用只能认为是非限定名称和完全限定名称,而永远不可能是限定名称。

复制代码
<?<span>php

namespace Blog;

</span><span>//</span><span>导入Common类</span>
<span>use</span><span> Blog\Article\Common;
</span><span>//</span><span>我想使用非限定名称调用Blog\Article\Common</span>
<span>$common_class_name</span> = 'Common'<span>;
</span><span>//</span><span>实际会被当作非限定名称,也就表示当前空间的Common类,但我当前类没有创建Common类</span>
<span>$common</span> = <span>new</span> <span>$common_class_name</span>(); <span>//</span><span>发生致命错误:Common类不存在

//我想使用限定名称调用Blog\Article\Common</span>
<span>$common_class_name</span> = 'Article\Common'<span>;
</span><span>//</span><span>实际会被当作完全限定名称,也就表示Article空间下的Common类,但我下面只定义了Blog\Article空间而不是Article空间</span>
<span>$common</span> = <span>new</span> <span>$common_class_name</span>(); <span>//</span><span>发生致命错误:Article\Common类不存在</span>
<span>

namespace Blog\Article;

</span><span>class</span><span> Common { }

</span>?>
登入後複製
复制代码

 

 

总结

我对PHP的命名空间刚刚接触,也不能随便给一些没有实践的建议。我个人认为命名空间的作用和功能都很强大,如果要写插件或者通用库的时候再也不用担心重名问题。不过如果项目进行到一定程度,要通过增加命名空间去解决重名问题,我觉得工作量不会比重构名字少。也不得不承认它的语法会对项目增加一定的复杂度,因此从项目一开始的时候就应该很好的规划它,并制定一个命名规范。

 

 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1129454.htmlTechArticlePHP命名空间(Namespace)初探,命名空间namespace 探完闭包[查看],再探命名空间。 对于命名空间,官方文档已经说得很详细[查看],我在这里...
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱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

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

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

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

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1325
25
PHP教程
1273
29
C# 教程
1252
24
說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? 說明PHP中的安全密碼散列(例如,password_hash,password_verify)。為什麼不使用MD5或SHA1? Apr 17, 2025 am 12:06 AM

在PHP中,應使用password_hash和password_verify函數實現安全的密碼哈希處理,不應使用MD5或SHA1。1)password_hash生成包含鹽值的哈希,增強安全性。 2)password_verify驗證密碼,通過比較哈希值確保安全。 3)MD5和SHA1易受攻擊且缺乏鹽值,不適合現代密碼安全。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型? PHP類型提示如何起作用,包括標量類型,返回類型,聯合類型和無效類型? Apr 17, 2025 am 12:25 AM

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP的持久相關性:它還活著嗎? PHP的持久相關性:它還活著嗎? Apr 14, 2025 am 12:12 AM

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP和Python:代碼示例和比較 PHP和Python:代碼示例和比較 Apr 15, 2025 am 12:07 AM

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

PHP與其他語言:比較 PHP與其他語言:比較 Apr 13, 2025 am 12:19 AM

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

See all articles