Note: 名为PHP或php的命名空间,以及以这些名字开头的命名空间(例如PHP\Classes)被保留用做语言内核使用,而不该该在用户空间的代码中使用php
定义命名空间
定义: 经过namespace关键字声明函数
子名命名空间:
与目录和文件的关系很像,PHP名命空间容许指定层次化的命名空间名称,这种使用分层次的方式定义的命名空间被称为子命名空间。编码
//定义命名空间 <?php //declare(encoding='UTF-8'); // namespace定义前面惟一合法语句,不是必须 namespace MyProject; …… ?> //定义子命名空间 <?php namespace MyProject\Sub\Level; …… ?>
说明:url
- 任意合法PHP代码均可以包含在命名空间中,但只有如下类型的代码受命名空间的影响:
类(包括抽象类和traits)
、接口
、函数
和常量
。 - 同一个命名空间能够定义在多个文件中,即容许将同一个命名空间的内容分割存放在不一样的文件中。
注意事项: 若是一个文件中包含命名空间,它必须在全部代码以前声明命名空间,在声明命名空间以前惟一合法的代码是用于定义源文件编码方式的declare语句,另外,全部非PHP代码包括空白符都不能出如今命名空间的声明以前。spa
在同一个文件中定义多个名命空间(不提倡,这种方式主要用于将多个PHP脚本合并在同一个文件中 )
定义方式有两种:.net
- 简单组合语法
<?php namespace MyProject; 代码段…… namespace AnotherProject; 代码段…… ?>
- 大括号语法
<?php namespace MyProject{ 代码段…… } namespace AnotherProject{ 代码段…… } ?>
若是是将全局的非命名空间中的代码与名命空间中的代码组合在一块儿,则只能使用大括号形式的语法。全局代码必须用一个不带名称的namespace语句加上大括号括起来:code
<?php namespace MyProject{ 代码段…… } namespace{ //全局空间 代码段…… } ?>
注意: 除了开始的declare语句外,命名空间的括号外不得有任何PHP代码。对象
使用名命空间:基础
(PHP 5 >= 5.3.0, PHP 7)接口
在讨论如何使用命名空间以前,必须了解 PHP 是如何知道要使用哪个命名空间中的元素的。能够将 PHP 命名空间与文件系统做一个简单的类比。字符串
在文件系统中访问一个文件有三种方式:
- 相对文件名形式,如foo.txt。它会被解析为 currentdirectory/foo.txt,其中 currentdirectory 表示当前目录。所以若是当前目录是 /home/foo,则该文件名被解析为/home/foo/foo.txt。
- 相对路径名形式如subdirectory/foo.txt。它会被解析为 currentdirectory/subdirectory/foo.txt。
- 绝对路径名形式如/main/foo.txt。它会被解析为/main/foo.txt。
PHP 命名空间中的元素使用一样的原理。例如,类名能够经过三种方式引用:
- 非限定名称,或不包含前缀的类名称,例如 $a=new foo(); 或 foo::staticmethod();。若是当前命名空间是 currentnamespace,foo 将被解析为 currentnamespace\foo。若是使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为foo。
备注: 若是命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。即:
若是在当前命名空间中没有找到函数或常量,则接着会尝试去全局空间中找。若是仍未找到,则此时会报错。,若是类没有在当前命名空间中定义,则不会去全局空间找。
详情参见使用命名空间:后备全局函数名称/常量名称
一节。
- 限定名称,或包含前缀的名称,例如 $a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod();。若是当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\subnamespace\foo。若是使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为subnamespace\foo。
- 彻底限定名称,或包含了全局前缀操做符的名称,例如, $a = new \currentnamespace\foo(); 或 \currentnamespace\foo::staticmethod();。在这种状况下,foo 老是被解析为代码中的文字名(literal name)currentnamespace\foo。
示例:
file1.php
<?php namespace Foo\Bar\subnamespace; const FOO=1; function foo(){} class foo{ static function staticmethod(){} } ?>
file2.php
<?php namespace Foo\Bar; include 'file1.php'; const FOO = 2; function foo() {} class foo { static function staticmethod() {} } /* 非限定名称 */ foo(); // 解析为 Foo\Bar\foo foo::staticmethod(); // 解析为类 Foo\Bar\foo的静态方法staticmethod。 echo FOO; // 解析为 Foo\Bar\FOO /* 限定名称 */ subnamespace\foo(); // 解析为函数 Foo\Bar\subnamespace\foo subnamespace\foo::staticmethod(); // 解析为类 Foo\Bar\subnamespace\foo,以及类的方法 staticmethod echo subnamespace\FOO; // 解析为常量 Foo\Bar\subnamespace\FOO /* 彻底限定名称 */ \Foo\Bar\foo(); // 解析为函数 Foo\Bar\foo \Foo\Bar\foo::staticmethod(); // 解析为类 Foo\Bar\foo, 以及类的方法 staticmethod echo \Foo\Bar\FOO; // 解析为常量 Foo\Bar\FOO ?>
注意: 访问任意全局类、函数或常量,均可以使用彻底限定名称,例如:\strlen()
或 \Exception
或 \INI_ALL
。
命名空间和动态语言特征
说明: 名命空间的实现会受到其语言自身的动态特征的影响。在使用动态的类名称、函数名称、常量名称时,须要使用【彻底】限定名称。
注意: 由于在动态的类名称、函数名称、常量名称中,限定名称和彻底限定名称没有区别,所以,其前导的反斜杠是没必要要的。
<?php namespace{ class classname{ function __construct(){ echo __METHOD__,"<br>"; } } function funcname(){ echo __FUNCTION__,"<br>"; } const constname = "global"; $a = 'classname'; $obj = new $a; //打印 classname::__construct $b = 'funcname'; $b(); // prints funcname echo constant('constname'), "<br>"; //打印 prints global } namespace namespacename{ class classname{ function __construct(){ echo __METHOD__,"<br>"; } } function funcname(){ echo __FUNCTION__,"<br>"; } const constname = "namespaced"; $a = 'classname'; $obj = new $a; //打印 classname::__construct $b = 'funcname'; $b(); // prints funcname echo constant('constname'), "<br>"; //打印 global echo '<hr>'; $a = '\namespacename\classname'; $obj = new $a; //打印 namespacename\classname::__construct $a = 'namespacename\classname'; $obj = new $a; //打印 namespacename\classname::__construct $b = 'namespacename\funcname'; $b(); //打印 namespacename\funcname $b = '\namespacename\funcname'; $b(); //打印 namespacename\funcname echo constant('\namespacename\constname'), "<br>"; // 打印 namespaced echo constant('namespacename\constname'), "<br>"; // 打印 namespaced } ?>
namespace关键字和__NAMESPACE__常量
PHP支持两种抽象的访问当前命名空间内部的方法:
1. __NAMESPACE__魔术常量
返回值: 包含当前名命空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它返回一个空字符串
该常量在动态建立类时颇有用:
<?php namespace MyProject; function get($classname){ $a=__NAMESPACE__.'\\'.$classname; return new $a; } ?>
2. namespace关键字
做用: 用来显式访问当前名命空间或子名命空间中的元素。它等价于类中的self操做符
名命空间中的代码
<?php namespace MyProject; use blah\blah as mine; blah\mine(); //Myproject\blah\mine() namespace\blah\mine(); //MyProject\blah\mine namespace\func(); //MyProject\func() namespace\sub\func(); //MyProject\sub\func() namaspace\cname::method(); MyProject\cname::method() $a=new namespace\sub\cname(); //MyProject\sub\cname $b=namespace\CONSTANT; //MyProject\CONSTANT ?>
全局代码
<?php namespace\func(); //func() namespace\sub\func(); //sub\func() namespace\cname::method(); //cname::method() $a=new namespace\sub\cname(); //sub\cname $b=namespace\CONSTANT; //CONSTANT
使用命名空间:别名/导入
PHP容许经过别名应用或导入外部的彻底限定名称。
全部支持名命空间的PHP版本都支持三种别名或导入方式:
- 为类名称使用别名
- 为接口使用别名
- 为名命空间使用别名
PHP5.6开始容许导入函数
或常量
或者为它们设置别名
导入关键字:
use
- 为了简化操做,PHP支持在一行中使用多个use语句,中间用‘,’隔开。
特别说明: 对命名空间中的名称(包含命名空间分隔符的彻底限定名称)来讲,前导的反斜杠是没必要要的也是不推荐的,由于导入的名称必须是彻底限定的,不会根据当前的名命空间做相对解析。
如下说的意思算是对上面内容的解释吧:
-
导入操做是在编译执行的,但动态的类名称、函数名称或常量名称则不是。(大概是说,导入是在编译期执行,而实际代码中的动态名称是在执行时肯定)
-
导入操做只影响非限定名称和限定名称。彻底限定名称因为是肯定的,故不受导入的影响。(大概是说,use 语句引用的时候都是彻底限定名称,而实际代码中使用过的时候要注意非限定名称、限定名称和彻底限定名称的使用)
两个示例:
导入和动态名称:
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // 实例化一个 My\Full\Classname 对象 $a = 'Another'; $obj = new $a; // 实际化一个 Another 对象 ?>
导入和彻底限定名称
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // instantiates object of class My\Full\Classname $obj = new \Another; // instantiates object of class Another $obj = new Another\thing; // instantiates object of class My\Full\Classname\thing $obj = new \Another\thing; // instantiates object of class Another\thing ?>
使用命名空间:后备全局函数/常量
重要: 在一个命名空间中,当 PHP 遇到一个非限定的类、函数或常量名称时,它使用不一样的优先策略来解析该名称。类名称老是解析到当前命名空间中的名称。所以在访问系统内部或不包含在命名空间中的类名称时,必须使用彻底限定名称。 对于函数和常量来讲,若是当前命名空间中不存在该函数或常量,PHP 会退而使用全局空间中的函数或常量