对于命名空间,官方文档已经说得很详细[查看],我在这里做了一下实践和总结。
命名空间一个最明确的目的就是解决重名问题,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 ArticleComment();
?>
可以看到,在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 ArticlePATH; ///article
echo ArticlegetCommentTotal(); //100
$article_comment = new ArticleComment();
?>
然后我的确得到了Article空间的元素数据。
子空间
命名空间的调用语法像文件路径一样是有道理的,它允许我们自定义子空间来描述各个空间之间的关系。
抱歉我忘了说,article和message board这两个模块其实都是处于同一个blog项目内。如果用命名空间来表达它们的关系,是这样:
//我用这样的命名空间表示处于blog下的article模块
namespace BlogArticle;
class Comment { }
//我用这样的命名空间表示处于blog下的message board模块
namespace BlogMessageBoard;
class Comment { }
//调用当前空间的类
$comment = new Comment();
//调用BlogArticle空间的类
$article_comment = new BlogArticleComment();
?>
而且,子空间还可以定义很多层次,比如说 BlogArticleArchivesDate
公共空间
我有一个common_inc.php脚本文件,里面有一些好用的函数和类:
function getIP() { }
class FilterXSS { }
?>
在一个命名空间里引入这个脚本,脚本里的元素不会归属到这个命名空间。如果这个脚本里没有定义其它命名空间,它的元素就始终处于公共空间中:
namespace BlogArticle;
//引入脚本文件
include './common_inc.php';
$filter_XSS = new FilterXSS(); //出现致命错误:找不到BlogArticleFilterXSS类
$filter_XSS = new FilterXSS(); //正确
?>
调用公共空间的方式是直接在元素名称前加 就可以了,否则PHP解析器会认为我想调用当前空间下的元素。除了自定义的元素,还包括PHP自带的元素,都属于公共空间。
要提一下,其实公共空间的函数和常量不用加 也可以正常调用(不明白PHP为什么要这样做),但是为了正确区分元素,还是建议调用函数的时候加上
名称术语
在说别名和导入之前,需要知道关于空间三种名称的术语,以及PHP是怎样解析它们的。官方文档说得非常好,我就直接拿来套了。
1.非限定名称,或不包含前缀的类名称,例如 $comment = new Comment();。如果当前命名空间是BlogArticle,Comment将被解析为BlogArticleComment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。
2.限定名称,或包含前缀的名称,例如 $comment = new ArticleComment();。如果当前的命名空间是Blog,则Comment会被解析为BlogArticleComment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。
3.完全限定名称,或包含了全局前缀操作符的名称,例如 $comment = new ArticleComment();。在这种情况下,Comment总是被解析为代码中的文字名(literal name)ArticleComment。
其实可以把这三种名称类比为文件名(例如 comment.php)、相对路径名(例如 ./article/comment.php)、绝对路径名(例如 /blog/article/comment.php),这样可能会更容易理解。
我用了几个示例来表示它们:
//创建空间Blog
namespace Blog;
class Comment { }
//非限定名称,表示当前Blog空间
//这个调用将被解析成 BlogComment();
$blog_comment = new Comment();
//限定名称,表示相对于Blog空间
//这个调用将被解析成 BlogArticleComment();
$article_comment = new ArticleComment(); //类前面没有反斜杆
//完全限定名称,表示绝对于Blog空间
//这个调用将被解析成 BlogComment();
$article_comment = new BlogComment(); //类前面有反斜杆
//完全限定名称,表示绝对于Blog空间
//这个调用将被解析成 BlogArticleComment();
$article_comment = new BlogArticleComment(); //类前面有反斜杆
//创建Blog的子空间Article
namespace BlogArticle;
class Comment { }
?>
其实之前我就一直在使用非限定名称和完全限定名称,现在它们终于可以叫出它们的名称了。
别名和导入
别名和导入可以看作是调用命名空间元素的一种快捷方式。PHP并不支持导入函数或常量。
它们都是通过使用use操作符来实现:
namespace BlogArticle;
class Comment { }
//创建一个BBS空间(我有打算开个论坛)
namespace BBS;
//导入一个命名空间
use BlogArticle;
//导入命名空间后可使用限定名称调用元素
$article_comment = new ArticleComment();
//为命名空间使用别名
use BlogArticle as Arte;
//使用别名代替空间名
$article_comment = new ArteComment();
//导入一个类
use BlogArticleComment;
//导入类后可使用非限定名称调用元素
$article_comment = new Comment();
//为类使用别名
use BlogArticleComment as Comt;
//使用别名代替空间名
$article_comment = new Comt();
?>
我注意到,如果导入元素的时候,当前空间有相同的名字元素将会怎样?显然结果会发生致命错误。
例:
namespace BlogArticle;
class Comment { }
namespace BBS;
class Comment { }
Class Comt { }
//导入一个类
use BlogArticleComment;
$article_comment = new Comment(); //与当前空间的Comment发生冲突,程序产生致命错误
//为类使用别名
use BlogArticleComment as Comt;
$article_comment = new Comt(); //与当前空间的Comt发生冲突,程序产生致命错误
?>
动态调用
PHP提供了namespace关键字和__NAMESPACE__魔法常量动态的访问元素,__NAMESPACE__可以通过组合字符串的形式来动态访问:
namespace BlogArticle;
const PATH = '/Blog/article';
class Comment { }
//namespace关键字表示当前空间
echo namespacePATH; ///Blog/article
$comment = new namespaceComment();
//魔法常量__NAMESPACE__的值是当前空间名称
echo __NAMESPACE__; //BlogArticle
//可以组合成字符串并调用
$comment_class_name = __NAMESPACE__ . 'Comment';
$comment = new $comment_class_name();
?>
字符串形式调用问题
上面的动态调用的例子中,我们看到了字符串形式的动态调用方式,如果要使用这种方式要注意两个问题。
1. 使用双引号的时候特殊字符可能被转义
namespace BlogArticle;
class name { }
//我是想调用BlogArticlename
$class_name = __NAMESPACE__ . "name"; //但是n将被转义为换行符
$name = new $class_name(); //发生致命错误
?>
2. 不会认为是限定名称
PHP在编译脚本的时候就确定了元素所在的空间,以及导入的情况。而在解析脚本时字符串形式调用只能认为是非限定名称和完全限定名称,而永远不可能是限定名称。
namespace Blog;
//导入Common类
use BlogArticleCommon;
//我想使用非限定名称调用BlogArticleCommon
$common_class_name = 'Common';
//实际会被当作非限定名称,也就表示当前空间的Common类,但我当前类没有创建Common类
$common = new $common_class_name(); //发生致命错误:Common类不存在
//我想使用限定名称调用BlogArticleCommon
$common_class_name = 'ArticleCommon';
//实际会被当作完全限定名称,也就表示Article空间下的Common类,但我下面只定义了BlogArticle空间而不是Article空间
$common = new $common_class_name(); //发生致命错误:ArticleCommon类不存在
namespace BlogArticle;
class Common { }
?>
总结
我对PHP的命名空间刚刚接触,也不能随便给一些没有实践的建议。我个人认为命名空间的作用和功能都很强大,如果要写插件或者通用库的时候再也不用担心重名问题。不过如果项目进行到一定程度,要通过增加命名空间去解决重名问题,我觉得工作量不会比重构名字少。也不得不承认它的语法会对项目增加一定的复杂度,因此从项目一开始的时候就应该很好的规划它,并制定一个命名规范。

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

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

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

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

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

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

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

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


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Dreamweaver CS6
视觉化网页开发工具

禅工作室 13.0.1
功能强大的PHP集成开发环境

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

Atom编辑器mac版下载
最流行的的开源编辑器