网络编程
位置:首页>> 网络编程>> php编程>> 详细解读php的命名空间(一)

详细解读php的命名空间(一)

作者:贝伦酱  发布时间:2023-06-19 08:02:59 

标签:php,命名空间

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__的使用,以及别名的使用等。

来源:http://blog.csdn.net/belen_xue/article/details/78875377

0
投稿

猜你喜欢

  • 搞前端应该对语义化并不陌生,每天都在说语义化,可什么是语义化,语义化究竟能给我们带来什么好处?参加web标准交流会的时候我向各位同学提出了我
  • 1 新建类库MyTestDLL2 右击项目“MyTestDLL”-》属性-》生成-》勾选“为COM互操作注册”3 打开 AssemblyIn
  • 阅读上一篇:微软建议的ASP性能优化28条守则(2) 技巧 5:不要将数据库连接缓存在 Application 或 Session 对象中
  • 那么,现在如果给出一个权限编号,要去检索出用后这个权限的用户集合,就会需要在逗号分隔的多个权限编号中去匹配给出的这个权限编号。如果使用lik
  • 1、from子句组装来自不同数据源的数据;  2、where子句基于指定的条件对记录行进行筛选;  3、group&nb
  • 分区表的概念 分区致力于解决支持极大表和索引的关键问题。它采用他们分解成较小和易于管理的称为分区的片(piece)的方法。一旦分区被定义,S
  • 1、纯粹的截取字符串function cutstr(thestr1,strlen) dim l,t,c&nbs
  • 无意中看到百度的页面代码,想到了一种声明写法,需要的朋友可以参考下。<!DOCTYPE html> <!--[if IE]
  • 【尝尝管理员的滋味】- 淡然看,其实一切都很简单IE的滤镜泄露是最大的危害,没有找到方法解决,所以禁用了滤镜。<!DOCTYPE ht
  • 五、过渡转化的使用在《mind hack》一书中,揭示了人脑鲜为人知的工作原理。其中提到了“突然的移动或闪烁会吸引人的注意力,这正是负责视觉
  • 1、requests 的常见用法requests 除了 url 之外,还有 params, data 和 files 三个参数,用于和服务器
  • 演示:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//
  • 如何检测某个对象是否有某个属性?第一想到的——没错,in:"prop" in obj这很完美,不过,还有不少人热衷下面的
  • asp使用session来防止表单多次被提交的方法。formtest.asp' 表单文件<%Randomize&nb
  • 我们知道,数组的sort方法可以对数组元素进行排序,默认是按ASCII字母表顺序排序。如果要根据其他的顺序排序就需要为sort方法提供一个比
  • 设计页面时,经常会从一个页面打开一个子窗口以供浏览者查看。通常,这种子窗口中的内容一经浏览者看过,对于浏览者而言就不再需要,而他们常常会忘记
  • 以前看过有人转换过的,当时仅仅惊叹了一下,就过去了,没有记下来,直至于用到的时候呢,开始到处找,找来找去都没有找不到痕迹了,心里也就郁郁寡欢
  • 简洁的隐藏垂直菜单在hover时将内容展开。这样的效果在JS里有很多个版本,但这个可以说是绝无仅有的CSS版本。此菜单可以在IE5.5,IE
  • 如何在SQL中启用全文检索功能?本文将通过实例向你剖折这个问题。这是一个全文索引的一个例子,首先在查询分析器中使用:use pubsgo--
  • 通过XSL转换XML文件 最近,我喜欢上了XML编程,但又苦于它的美观程度又不够,找了许多书才搞定。用XML好是蛮好,但它还是不太适合做显示
手机版 网络编程 asp之家 www.aspxhome.com