青岛网站推广优化公司,北京 网站建设 招标信息,wordpress批量定时发布,手机qq邮箱发布了wordpress1.什么是命名空间#xff0c;官方文档定义为#xff1a; 什么是命名空间#xff1f;从广义上来说#xff0c;命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如#xff0c;在操作系统中目录用来将相关文件分组#xff0c;对于目录中的文件来说…1.什么是命名空间官方文档定义为 什么是命名空间从广义上来说命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如在操作系统中目录用来将相关文件分组对于目录中的文件来说它就扮演了命名空间的角色。具体举个例子文件 foo.txt 可以同时在目录/home/greg 和 /home/other 中存在但在同一个目录中不能存在两个 foo.txt 文件。另外在目录 /home/greg 外访问 foo.txt 文件时我们必须将目录名以及目录分隔符放在文件名之前得到 /home/greg/foo.txt。这个原理应用到程序设计领域就是命名空间的概念。 2.命名空间的作用官方定义为 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名或简短的名称提高源代码的可读 其实命名空间的作用就是解决类、函数、常量重名的问题变量名重复可以放到不同的函数中函数名重复可以放到不同的类中那类名重复呢就可以用命名空间解决 3.如何定义一个命名空间 namespace xx; 范围从这一行开始到下一个命名空间的开始 注意事项在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句。另外所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前 虽然任意合法的PHP代码都可以包含在命名空间中但只有以下类型的代码受命名空间的影响它们是类包括抽象类和traits、接口、函数和常量。另外与PHP其它的语言特征不同同一个命名空间可以定义在多个文件中即允许将同一个命名空间的内容分割存放在不同的文件中。 4.定义子命名空间 与目录和文件的关系很象PHP 命名空间也允许指定层次化的命名空间的名称。因此命名空间的名字可以使用分层次的方式定义 ?php namespace MyProject\Sub\Level; const CONNECT_OK 1; class Connection { /* ... */ } function connect() { /* ... */ } ? 上面的例子创建了常量MyProject\Sub\Level\CONNECT_OK类 MyProject\Sub\Level\Connection和函数 MyProject\Sub\Level\connect。 5.也可以在同一个文件中定义多个命名空间。在同一个文件中定义多个命名空间有两种语法形式。 ?php namespace MyProject; const CONNECT_OK 1; class Connection { /* ... */ } function connect() { /* ... */ } namespace AnotherProject; const CONNECT_OK 1; class Connection { /* ... */ } function connect() { /* ... */ } ? 不建议使用这种语法在单个文件中定义多个命名空间建议使用下面大括号的语法定义命名空间 ?php namespace MyProject { const CONNECT_OK 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace AnotherProject { const CONNECT_OK 1; class Connection { /* ... */ } function connect() { /* ... */ } } ? 在实际编程中非常不提倡在一个文件中定义多个命名空间。这种方式的主要用于将多个 PHP 脚本合并在同一个文件中。 将全局的非命名空间中的代码与命名空间中的代码组合在一起只能使用大括号形式的语法。全局代码必须用一个不带名称的 namespace 语句加上大括号括起来例如 ?php declare(encodingUTF-8); // 除了开始的declare语句外命名空间的括号外不得有任何PHP代码。 namespace MyProject { const CONNECT_OK 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace { // global code session_start(); $a MyProject\connect(); echo MyProject\Connection::start(); } ? 6.使用命名空间 注明 本文提到的常量PHP5.3开始const关键字可以用在类的外部。const和define都是用来声明常量的它们的区别不详述但是在命名空间里define的作用是全局的而const则作用于当前空间。我在文中提到的常量是指使用const声明的常量。 命名空间将代码划分出不同的空间区域每个空间的常量、函数、类为了偷懒我下边都将它们称为元素的名字互不影响 这个有点类似我们常常提到的‘封装的概念。 创建一个命名空间需要使用namespace关键字这样 复制代码代码如下: ?php //创建一个名为Article的命名空间namespace Article; ? 要注意的是当前脚本文件的第一个命名空间前面不能有任何代码下面的写法都是错误的 复制代码代码如下: //例一//在脚本前面写了一些逻辑代码 ?php $path /; class Comment { } namespace Article; ? //例二//在脚本前面输出了一些字符 html/html?php namespace Article; ? 为什么要说第一个命名空间呢因为同一脚本文件中可以创建多个命名空间。 下面我创建了两个命名空间顺便为这两个空间各自添加了一个Comment类元素 复制代码代码如下: ?php //创建一个名为Article的命名空间namespace Article; //此Comment属于Article空间的元素class Comment { } //创建一个名为MessageBoard的命名空间namespace MessageBoard; //此Comment属于MessageBoard空间的元素class Comment { }? 在不同空间之间不可以直接调用其它元素需要使用命名空间的语法 复制代码代码如下: ?php namespace Article; class Comment { } namespace MessageBoard; class Comment { } //调用当前空间MessageBoard的Comment类$comment new Comment(); //调用Article空间的Comment类$article_comment new \Article\Comment(); ? 可以看到在MessageBoard空间中调用article空间里的Comment类时使用了一种像文件路径的语法 \空间名\元素名 除了类之外对函数和常量的用法是一样的下面我为两个空间创建了新的元素并在MessageBoard空间中输出了它们的值。 复制代码代码如下: ?php 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_boardecho getCommentTotal(); //300$comment new Comment(); //调用Article空间的常量、函数和类echo \Article\PATH; ///articleecho \Article\getCommentTotal(); //100$article_comment new \Article\Comment(); ? 然后我的确得到了Article空间的元素数据。 子空间命名空间的调用语法像文件路径一样是有道理的它允许我们自定义子空间来描述各个空间之间的关系。 抱歉我忘了说article和message board这两个模块其实都是处于同一个blog项目内。如果用命名空间来表达它们的关系是这样 复制代码代码如下: ?php //我用这样的命名空间表示处于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脚本文件里面有一些好用的函数和类 复制代码代码如下: ?php function getIP() { } class FilterXSS { } ? 在一个命名空间里引入这个脚本脚本里的元素不会归属到这个命名空间。如果这个脚本里没有定义其它命名空间它的元素就始终处于公共空间中 复制代码代码如下: ?php namespace Blog\Article; //引入脚本文件include ./common_inc.php; $filter_XSS new FilterXSS(); //出现致命错误找不到Blog\Article\FilterXSS类 $filter_XSS new \FilterXSS(); //正确 ? 调用公共空间的方式是直接在元素名称前加 \ 就可以了否则PHP解析器会认为我想调用当前空间下的元素。除了自定义的元素还包括PHP自带的元素都属于公共空间。 要提一下其实公共空间的函数和常量不用加 \ 也可以正常调用不明白PHP为什么要这样做但是为了正确区分元素还是建议调用函数的时候加上 \ 7.名称术语 在说别名和导入之前需要知道关于空间三种名称的术语以及PHP是怎样解析它们的。官方文档说得非常好我就直接拿来套了。 1.非限定名称或不包含前缀的类名称例如 $comment new Comment();。如果当前命名空间是Blog\ArticleComment将被解析为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这样可能会更容易理解。 我用了几个示例来表示它们 复制代码代码如下: ?php //创建空间Blognamespace 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的子空间Articlenamespace Blog\Article; class Comment { } ? 其实之前我就一直在使用非限定名称和完全限定名称现在它们终于可以叫出它们的名称了。 别名和导入别名和导入可以看作是调用命名空间元素的一种快捷方式。PHP并不支持导入函数或常量。 它们都是通过使用use操作符来实现 复制代码代码如下: ?php 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(); ? 我注意到如果导入元素的时候当前空间有相同的名字元素将会怎样显然结果会发生致命错误。 例 复制代码代码如下: ?php 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__可以通过组合字符串的形式来动态访问 复制代码代码如下: ?php 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. 使用双引号的时候特殊字符可能被转义 复制代码代码如下: ?php namespace Blog\Article; class name { } //我是想调用Blog\Article\name$class_name __NAMESPACE__ . \name; //但是\n将被转义为换行符 $name new $class_name(); //发生致命错误 ? 2. 不会认为是限定名称 PHP在编译脚本的时候就确定了元素所在的空间以及导入的情况。而在解析脚本时字符串形式调用只能认为是非限定名称和完全限定名称而永远不可能是限定名称。 复制代码代码如下: ?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的命名空间刚刚接触也不能随便给一些没有实践的建议。我个人认为命名空间的作用和功能都很强大如果要写插件或者通用库的时候再也不用担心重名问题。不过如果项目进行到一定程度要通过增加命名空间去解决重名问题我觉得工作量不会比重构名字少。也不得不承认它的语法会对项目增加一定的复杂度因此从项目一开始的时候就应该很好的规划它并制定一个命名规范。转载于:https://www.cnblogs.com/skl-bobo/p/10438792.html