搜尋
首頁後端開發php教程PHP命名空间(Namespace)初探,命名空间namespace_PHP教程

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
可以在PHP會話中存儲哪些數據?可以在PHP會話中存儲哪些數據?May 02, 2025 am 12:17 AM

phpsessionscanStorestrings,數字,數組和原始物。

您如何開始PHP會話?您如何開始PHP會話?May 02, 2025 am 12:16 AM

tostartaphpsession,usesesses_start()attheScript'Sbeginning.1)placeitbeforeanyOutputtosetThesessionCookie.2)useSessionsforuserDatalikeloginstatusorshoppingcarts.3)regenerateSessiveIdStopreventFentfixationAttacks.s.4)考慮使用AttActAcks.s.s.4)

什麼是會話再生,如何提高安全性?什麼是會話再生,如何提高安全性?May 02, 2025 am 12:15 AM

會話再生是指在用戶進行敏感操作時生成新會話ID並使舊ID失效,以防會話固定攻擊。實現步驟包括:1.檢測敏感操作,2.生成新會話ID,3.銷毀舊會話ID,4.更新用戶端會話信息。

使用PHP會話時有哪些性能考慮?使用PHP會話時有哪些性能考慮?May 02, 2025 am 12:11 AM

PHP会话对应用性能有显著影响。优化方法包括:1.使用数据库存储会话数据,提升响应速度;2.减少会话数据使用,只存储必要信息;3.采用非阻塞会话处理器,提高并发能力;4.调整会话过期时间,平衡用户体验和服务器负担;5.使用持久会话,减少数据读写次数。

PHP會話與Cookie有何不同?PHP會話與Cookie有何不同?May 02, 2025 am 12:03 AM

PHPsessionsareserver-side,whilecookiesareclient-side.1)Sessionsstoredataontheserver,aremoresecure,andhandlelargerdata.2)Cookiesstoredataontheclient,arelesssecure,andlimitedinsize.Usesessionsforsensitivedataandcookiesfornon-sensitive,client-sidedata.

PHP如何識別用戶的會話?PHP如何識別用戶的會話?May 01, 2025 am 12:23 AM

phpIdentifiesauser'ssessionSessionSessionCookiesAndSessionId.1)whiwsession_start()被稱為,phpgeneratesainiquesesesessionIdStoredInacookInAcookInAcienamedInAcienamedphpsessIdontheuser'sbrowser'sbrowser.2)thisIdallowSphptpptpptpptpptpptpptpptoretoreteretrieetrieetrieetrieetrieetrieetreetrieetrieetrieetrieetremthafromtheserver。

確保PHP會議的一些最佳實踐是什麼?確保PHP會議的一些最佳實踐是什麼?May 01, 2025 am 12:22 AM

PHP會話的安全可以通過以下措施實現:1.使用session_regenerate_id()在用戶登錄或重要操作時重新生成會話ID。 2.通過HTTPS協議加密傳輸會話ID。 3.使用session_save_path()指定安全目錄存儲會話數據,並正確設置權限。

PHP會話文件默認存儲在哪裡?PHP會話文件默認存儲在哪裡?May 01, 2025 am 12:15 AM

phpsessionFilesArestoredIntheDirectorySpecifiedBysession.save_path,通常是/tmponunix-likesystemsorc:\ windows \ windows \ temponwindows.tocustomizethis:tocustomizEthis:1)useession_save_save_save_path_path()

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

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

熱工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器