音效素材网提供各类素材,打造精品素材网站!

站内导航 站长工具 投稿中心 手机访问

音效素材

详细解读php的命名空间(一)
日期:2021-09-06 20:02:56   来源:脚本之家

php的命名空间功能已经出来很久了,但是一直以来没怎么深究过,这次赶着有时间所以特意翻着手册做一个整理和总结帮助自己完善完善,原本准备一篇写完,但发现内容其实还是蛮多的,放一起太长看着累,所以分两篇博客要好些。

一:命名空间概念:命名空间是一种封装事物的方法,类似于目录和文件。

命名空间解决的问题(手册上也写的很清楚,下面按照自己的理解简化了):

1:解决程序编写者自己写的类、常量、函数和php内部的或者第三方的出现名称冲突的情况。

2:创建别名,帮助解决类、常量、函数名称过长的情况,帮助提高代码的可读性,另外名称过长其实通常都是因为为了缓解第一类问题导致的。

二:如何定义命名空间

1:命名空间用关键字namespace声明,同时命名空间必须位于其他代码之前,包括任何非php代码以及空白符(php的declare关键字除外),否则会抛出一个fatal error。

例如:

<?php 
namespace Index; 
?> 

注意1:如果命名空间namespace前没有任何代码及空白符,但还是出现fatal error,这个应该是由于bom头导致的,去掉bom头就可以了。
注意2:在命名空间下,虽然可以放置所有合法的php代码,但是受命名空间影响的仅有类(抽象类以及traits)和接口、常量和函数。

2:与目录和文件的关系很象,PHP 命名空间也允许指定层次化的命名空间的名称。因此,命名空间的名字可以使用分层次的方式定义,分隔符是\。

例如:

<?php 
namespace Index\Col\File; 
define('MESSAGE','hello world'); 
?> 

3:一个文件中可以定义多个命名空间,定义的语法有两种,一种是简单组合语法,另一种是大括号形式语法,另外一个文件定义多个命名空间的使用一般是多个文件合并成一个文件的场景,但不到万不得已最好不要这样,因为这样增加了代码的复杂度,可读性会降低,一般情况也没有这种使用的必要

简单组合语法:

<?php 
namespace Index; 
const INSTANCE=1; 
 
namespace Col; 
const INSTANCE=2; 
?> 

大括号语法,一个文件多个命名空间,如果还需要写上非命名空间的代码,就只能用大括号语法,并且非命名空间代码用namespace声明一个没有名称的命名空间,再用大括号即可:

<?php 
/*命名空间Index*/ 
namespace Index{ 
  const INSTANCE=1; 
} 
 
/*命名空间Col*/ 
namespace Col{ 
  const INSTANCE=2; 
} 
 
/*全局非命名空间代码*/ 
namespace { 
  const INSTANCE=3; 
} 
?> 

4:多个不同的文件可以定义同一个命名空间,也就是说同一个命名空间的内容可以分别存储到多个不同的文件中,这里就不举例了。

三:命名空间的识别原理

命名空间的使用原理有三种情况,手册上其实说的详细但可能因为翻译问题导致一些凌乱,这里我简化一下用自己的例子梳理一下:

1:没有限定名称,也就是直接使用要读取的类、常量、函数、接口名称,这种情况会读取该内容所属的命名空间的类、常量、函数、接口名称,但如果命名空间内没有相关的数据,如果是类和接口名称会返回fatal error,如果是函数和常量会自动读取全局的函数和常量,如果全局中也没有,才会报fatal error。

下面举例:

<?php 
/*全局非命名空间代码*/ 
namespace { 
  const INSTANCE=1; 
 
  function test(){ 
    echo 1; 
  } 
 
  class foo{ 
    static function fool(){ 
          echo 1; 
        } 
  } 
 
  var_dump(INSTANCE);   //打印出来的是1 
 
  test();       //输出1 
 
  foo::fool();      //输出1 
 
} 
 
/*命名空间Index*/ 
namespace Index{ 
  const INSTANCE=2; 
 
  function test(){ 
    echo 2; 
  } 
 
  class foo{ 
    static function fool(){ 
          echo 2; 
        } 
  } 
 
  var_dump(INSTANCE);   //打印出来的是2 
 
  test();     //输出2 
 
  foo::fool();    //输出2 
} 
 
/*命名空间Col*/ 
namespace Col{ 
  const INSTANCE=3; 
 
  function test(){ 
    echo 3; 
  } 
 
  class foo{ 
    static function fool(){ 
          echo 3; 
        } 
  } 
 
  var_dump(INSTANCE);   //打印出来的是3 
 
  test();     //输出2 
   
  foo::fool();    //输出2 
} 
?>

上面的例子每个命名空间里输出的都没有限定名称,所以会得到当前命名空间下设置的对应数据值。

如果当前命名空间没有设置,函数和常量则会读取全局设置的对应数据值,全局没有对应的才会报fatal error,类和接口都会直接报fatal error,如下面代码所示。

<?php 
/*全局非命名空间代码*/ 
namespace { 
  const INSTANCE=1;  
  function test(){ 
    echo 1; 
  } 
 
  class foo{ 
    static function fool(){ 
          echo 1; 
        } 
  } 
 
  var_dump(INSTANCE);   //打印出来的是1  
  test();     //输出1  
  foo::fool();    //输出1  
} 
 
/*命名空间Index*/ 
namespace Index{ 
  var_dump(INSTANCE);   //打印出来的是1  
  test();     //输出1  
  foo::fool();    //fatal error 
 
} 
?> 

2:限定名称,分为两种情况,一种是包含前缀的限定名称情况,一种是包含全局限定名称的情况。手册上将这两种单独分开了,但我觉得这两种可以合并成一起说,他们都是有限定名称,只是前者没有全局限定,后者有全局限定。

①包含前缀的限定名称,这种前缀可以有多个或者一个层级,但最左侧不能为\全局限定词,这种情况会读取该代码所在命名空间加上该前缀限定名称所对应数据,也就是:

所处命名空间\前缀限定\名称来读取,如果该代码是全局没有命名空间的,则直接用前缀限定名称来读取,也就是:前缀限定\名称来读取。

实例代码:

<?php 
/*命名空间Col\Index*/ 
namespace Col\Index{ 
  const INSTANCE=1; 
} 
 
/*命名空间Index*/ 
namespace Index{ 
  const INSTANCE=2; 
} 
 
/*命名空间Col*/ 
namespace Col{ 
  const INSTANCE=3; 
  var_dump(Index\INSTANCE); //打印出来的是1 读取的是Col\Index\INSTANCE 
} 
 
/*全局非命名空间代码*/ 
namespace { 
  const INSTANCE=4; 
  var_dump(Index\INSTANCE); //打印出来的是2 读取的是Index\INSTANCE 
} 
 
?> 

②全局限定前缀名称:也就是在最左侧有全局操作符\进行修饰的前缀限定名称,当然也可以没有前缀限定直接全局操作符\加上名称也是可以的。但加上全局操作符后就跟目录里的绝对路径一样,只会按照全局限定后的所设置的进行读取。

具体实例如下:

<?php 
/*命名空间Col\Index*/ 
namespace Col\Index{ 
  const INSTANCE=1; 
} 
 
/*命名空间Index*/ 
namespace Index{ 
  const INSTANCE=2; 
} 
 
/*命名空间Col*/ 
namespace Col{ 
  const INSTANCE=3; 
  var_dump(\Index\INSTANCE); //打印出来的是2 读取的是Index\INSTANCE 
} 
 
/*全局非命名空间代码*/ 
namespace { 
  const INSTANCE=4; 
  var_dump(\Index\INSTANCE); //打印出来的是2 读取的是Index\INSTANCE 
} 
 
namespace Lin{ 
  const INSTANCE=5; 
  var_dump(\INSTANCE); //打印出来的是4 读取的是INSTANCE,是全局非命名空间里的INSTANCE,如果没有全局操作符\,读取的会是当前命名空间的Lin\INSTANCE=5 
} 
 
?> 

四:命名空间在字符串中的转义

有时候命名空间会放在字符串中使用,如果是单引号不会通过编译器解释,所以没有任何问题,但是如果是双引号,那么就会有些意外情况了,要知道双引号里的内容是需要经过编译器进行解释然后再进行输出的,而\在编译器里的解释容易造成歧义

例如"index\name"这里就有\n会被解释成换行,除此之外还有很多这种造成意外的情况。

因此一般我们推荐命名空间如果要放在字符串中使用,最好使用单引号,一是效率,二是安全,如果使用双引号,则必须增加一个\进行转义避免歧义,例如"index\\name"这样就没有问题了。

随手双引号的举个例子:

<?php 
/*全局非命名空间代码*/ 
namespace Index\Name{ 
  class foo{ 
    function __construct(){ 
      echo 2; 
    } 
  } 
} 
 
namespace{ 
  $a= "Index\\Name\\foo"; //用\转义了\所以可以正常运行,但是如果去掉转义的话会报错Class 'Index\Nameoo',因为/f被解释成了换页符 
  $obj=new $a; 
} 

这部分碍于篇幅就暂时到这里了,下一篇主要总结命名空间里的namespace和__NAMESPACE__的使用,以及别名的使用等。

    您感兴趣的教程

    在docker中安装mysql详解

    本篇文章主要介绍了在docker中安装mysql详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编...

    详解 安装 docker mysql

    win10中文输入法仅在桌面显示怎么办?

    win10中文输入法仅在桌面显示怎么办?

    win10系统使用搜狗,QQ输入法只有在显示桌面的时候才出来,在使用其他程序输入框里面却只能输入字母数字,win10中...

    win10 中文输入法

    一分钟掌握linux系统目录结构

    这篇文章主要介绍了linux系统目录结构,通过结构图和多张表格了解linux系统目录结构,感兴趣的小伙伴们可以参考一...

    结构 目录 系统 linux

    PHP程序员玩转Linux系列 Linux和Windows安装

    这篇文章主要为大家详细介绍了PHP程序员玩转Linux系列文章,Linux和Windows安装nginx教程,具有一定的参考价值,感兴趣...

    玩转 程序员 安装 系列 PHP

    win10怎么安装杜比音效Doby V4.1 win10安装杜

    第四代杜比®家庭影院®技术包含了一整套协同工作的技术,让PC 发出清晰的环绕声同时第四代杜比家庭影院技术...

    win10杜比音效

    纯CSS实现iOS风格打开关闭选择框功能

    这篇文章主要介绍了纯CSS实现iOS风格打开关闭选择框,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作...

    css ios c

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的

    Win7给电脑C盘扩容的办法大家知道吗?当系统分区C盘空间不足时,就需要给它扩容了,如果不管,C盘没有足够的空间...

    Win7 C盘 扩容

    百度推广竞品词的投放策略

    SEM是基于关键词搜索的营销活动。作为推广人员,我们所做的工作,就是打理成千上万的关键词,关注它们的质量度...

    百度推广 竞品词

    Visual Studio Code(vscode) git的使用教程

    这篇文章主要介绍了详解Visual Studio Code(vscode) git的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...

    教程 Studio Visual Code git

    七牛云储存创始人分享七牛的创立故事与

    这篇文章主要介绍了七牛云储存创始人分享七牛的创立故事与对Go语言的应用,七牛选用Go语言这门新兴的编程语言进行...

    七牛 Go语言

    Win10预览版Mobile 10547即将发布 9月19日上午

    微软副总裁Gabriel Aul的Twitter透露了 Win10 Mobile预览版10536即将发布,他表示该版本已进入内部慢速版阶段,发布时间目...

    Win10 预览版

    HTML标签meta总结,HTML5 head meta 属性整理

    移动前端开发中添加一些webkit专属的HTML5头部标签,帮助浏览器更好解析HTML代码,更好地将移动web前端页面表现出来...

    移动端html5模拟长按事件的实现方法

    这篇文章主要介绍了移动端html5模拟长按事件的实现方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家...

    移动端 html5 长按

    HTML常用meta大全(推荐)

    这篇文章主要介绍了HTML常用meta大全(推荐),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    cdr怎么把图片转换成位图? cdr图片转换为位图的教程

    cdr怎么把图片转换成位图? cdr图片转换为

    cdr怎么把图片转换成位图?cdr中插入的图片想要转换成位图,该怎么转换呢?下面我们就来看看cdr图片转换为位图的...

    cdr 图片 位图

    win10系统怎么录屏?win10系统自带录屏详细教程

    win10系统怎么录屏?win10系统自带录屏详细

    当我们是使用win10系统的时候,想要录制电脑上的画面,这时候有人会想到下个第三方软件,其实可以用电脑上的自带...

    win10 系统自带录屏 详细教程

    + 更多教程 +
    ASP编程JSP编程PHP编程.NET编程python编程