搜尋
首頁後端開發php教程PHP命名空间(Namespace)的使用详解_php实例

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

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

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

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


注明:

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


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

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

复制代码 代码如下:

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

?>


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

//例一
//在脚本前面写了一些逻辑代码

$path = "/";

class Comment { }

namespace Article;

?>

 

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


namespace Article;

?>


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

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

复制代码 代码如下:

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

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


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

//此Comment属于MessageBoard空间的元素
class Comment { }
?>


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

namespace Article;

class Comment { }


namespace MessageBoard;

class Comment { }

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

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

?>


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

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

复制代码 代码如下:

namespace Article;

const PATH = '/article';

function getCommentTotal() {
    return 100;
}

class Comment { }


namespace MessageBoard;

const PATH = '/message_board';

function getCommentTotal() {
    return 300;
}

class Comment { }

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

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

?>


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


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

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

复制代码 代码如下:

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

class Comment { }


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

class Comment { }

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

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

?>


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


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

复制代码 代码如下:

function getIP() { }

class FilterXSS { }

?>


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

namespace Blog\Article;

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

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

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

?>


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

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


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

1.非限定名称,或不包含前缀的类名称,例如 $comment = new Comment();。如果当前命名空间是Blog\Article,Comment将被解析为Blog\Article\Comment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。

2.限定名称,或包含前缀的名称,例如 $comment = new Article\Comment();。如果当前的命名空间是Blog,则Comment会被解析为Blog\Article\Comment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。

3.完全限定名称,或包含了全局前缀操作符的名称,例如 $comment = new \Article\Comment();。在这种情况下,Comment总是被解析为代码中的文字名(literal name)Article\Comment。
 

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

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

复制代码 代码如下:

//创建空间Blog
namespace Blog;

class Comment { }

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

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

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

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


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

class Comment { }

?>


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


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

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

复制代码 代码如下:

namespace Blog\Article;

class Comment { }


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

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

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

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

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

?>


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

例:

复制代码 代码如下:

namespace Blog\Article;

class Comment { }


namespace BBS;

class Comment { }

Class Comt { }


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

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

?>


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

namespace Blog\Article;

const PATH = '/Blog/article';

class Comment { }


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

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

?>


字符串形式调用问题

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

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

复制代码 代码如下:

namespace Blog\Article;

class name { }

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

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

?>


2. 不会认为是限定名称

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

复制代码 代码如下:

namespace Blog;

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

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


namespace Blog\Article;

class Common { }

?>


总结
我对PHP的命名空间刚刚接触,也不能随便给一些没有实践的建议。我个人认为命名空间的作用和功能都很强大,如果要写插件或者通用库的时候再也不用担心重名问题。不过如果项目进行到一定程度,要通过增加命名空间去解决重名问题,我觉得工作量不会比重构名字少。也不得不承认它的语法会对项目增加一定的复杂度,因此从项目一开始的时候就应该很好的规划它,并制定一个命名规范。
陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
PHP8.0中的namespace合并PHP8.0中的namespace合并May 14, 2023 am 08:43 AM

随着技术的不断发展,PHP语言正在不断地更新和完善。PHP8.0作为最新版本的PHP语言,在功能上比之前的版本更加强大,其中一个重要的特性就是namespace合并。那么,namespace合并是什么呢?它又有什么用处?下面我们来详细探讨一下。namespace是PHP中一种用来区分不同代码的命名空间,它可以让我们在代码中使用同名类、函数或常量。在之前的版本

如何移除stickynotesnamespace如何移除stickynotesnamespaceDec 27, 2023 pm 01:51 PM

我们在使用win7系统的时候,会发现有一个stickynotes工具。stickynotes其实就是类似于一个电子便签本一样的功能,如果想要删除字需要在控制面板中对其进行卸载即可。stickynotesnamespace是什么怎么删除方法一:找到--方法二:找到,在后面点击删除即可方法三:使用第三方软件进行粉碎删除StickyNotes是什么它是一个系统自带的便签工具,和便利贴类似能够悬浮在桌面上,方便用户们记下重要的事情。平时该软件处于影藏状态,如果有需要的话是可以在指定的时间跳出并提醒用户们

PHP命名空间的使用方法及常见问题解答PHP命名空间的使用方法及常见问题解答Jun 09, 2023 am 08:15 AM

随着PHP语言的发展,命名空间的概念逐渐被引入到PHP中。命名空间(Namespace)是一种组织代码结构的方法,可以避免命名冲突和代码混乱。在本文中,我们将探讨PHP命名空间的使用方法及常见问题解答。一、命名空间的定义命名空间(Namespace)是PHP5.3引进的一个新特性,它可以让开发者更好地组织自己的代码。命名空间是一个标识符(Identifier

PHP中的命名空间使用技巧PHP中的命名空间使用技巧May 27, 2023 am 11:01 AM

随着PHP的发展,代码量不断增加,代码的组织结构变得越来越重要。在使用PHP时,命名空间是一个非常重要的概念,它可以帮助我们更好地组织代码,解决命名冲突等问题,提高代码的可读性和可维护性。本文将介绍如何使用PHP中的命名空间,以及一些常用的使用技巧。一、命名空间的基本概念命名空间是一种将相关的类、接口、函数等组织起来的方式。在PHP中,命名空间使用关键字"n

PHP命名空间加载错误的处理方法及生成相关报错提示PHP命名空间加载错误的处理方法及生成相关报错提示Aug 07, 2023 am 11:37 AM

PHP命名空间加载错误的处理方法及生成相关报错提示在PHP开发中,命名空间是一种很重要的概念,它可以帮助我们组织和管理代码,避免命名冲突。然而,在使用命名空间时,有时候会出现一些加载错误。这些错误可能是由于命名空间的定义不正确,或者是加载文件路径不正确导致的。本文将介绍一些常见的命名空间加载错误,并给出相应的处理方法,以及如何生成相关报错提示。一、命名空间定

如何使用PHP7的NameSpace和Use关键字组织代码的结构?如何使用PHP7的NameSpace和Use关键字组织代码的结构?Oct 19, 2023 am 08:07 AM

如何使用PHP7的NameSpace和Use关键字组织代码的结构?引言:在软件开发中,代码的组织结构是非常重要的,它直接关系到代码的可读性、可维护性和可扩展性。随着PHP版本的不断迭代,PHP7引入了NameSpace和Use关键字,这为我们提供了更多灵活性和便利性。本文将介绍如何使用PHP7的NameSpace和Use关键字来组织代码的结构,并提供具体的代

分析PHP面向对象编程中的命名空间分析PHP面向对象编程中的命名空间Aug 10, 2023 pm 02:12 PM

PHP是一种非常常用的脚本语言,广泛应用于Web开发中。随着项目规模的增大,代码的复杂度也在增加,为了更好地管理和组织代码,PHP引入了命名空间(namespace)的概念。本文将分析PHP面向对象编程中的命名空间,并给出相应的代码示例。命名空间的概念命名空间是一种将代码按照逻辑分组的机制,类似于文件夹(目录)在文件系统中的作用。它可以防止不同类之间的命名冲

PHP命名空间错误的问题及如何解决PHP命名空间错误的问题及如何解决May 11, 2023 am 09:10 AM

随着现代编程语言的发展,命名空间已经成为了一个广泛应用的概念。在PHP语言中,命名空间也得到了广泛的应用,并且成为了一个必要的特性,它可以帮助我们避免命名冲突,组织代码结构等。但这同时也带来了一些问题,其中之一就是命名空间错误问题。本文将讨论PHP命名空间错误问题,并提供解决方案。一、什么是PHP命名空间?在介绍PHP命名空间错误问题之前,我们需要先了解一下

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脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

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

mPDF

mPDF

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

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器