命名空间的基本使用
什么是命名空间?从广义上来说,命名空间是一种封装事物的方法,在很多的地方都可以见到这种抽象的概念。
例如,在操作系统中的目录用来将相关的文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。
在PHP中,命名空间用来解决在编写类库或者应用程序时创建可重用的代码如类或函数时碰到的两类问题:
- 问题1:用户编写的PHP代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
- 问题2:为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高代码的可读性。
下面看两个常量、函数、类的冲突代码,注意以下代码会报错
例子1:函数的冲突问题,系统函数不能再次声明,声明过的函数不能再次声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php //冲突问题 以下代码将会报错 /*和系统函数冲突 function time(){ echo '不能声明 系统函数的函数名称'; } time(); */ function test(){ echo 'test 函数'; } test(); /*声明过的函数不能重复声明 function test(){ echo '第二个test函数'; } test(); */ |
例子2:引入文件之后,两个文件中不能有同名的常量或者同名的类
1 2 3 4 5 6 7 8 9 10 |
<?php // 常量和类的冲突,因为在2_1.php重复声明了这个常量 const MYNUM = 123; class MyClass { } include '2_1.php'; |
1 2 3 4 5 6 |
<?php const MYNUM = 123; class MyClass { } |
命名空间的定义
命名空间通过关键字namespace来声明。如果一个文件中包含命名空间,它必须在其他所有代码之前声明命名空间。
命名空间的定义方式有两种,任选其一:
方式一:
1 2 |
namespace MyProject1; /*代码内容*/ |
方式二:
1 2 3 |
namespace Myproject2{ /*内容代码*/ } |
例子3:把同名的函数放在不同的命名空间中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php namespace MySpace{ function test() { echo 'test1'.'<hr>'; } //调用 test(); } namespace MySpace2{ function test() { echo 'test2'; } test(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php namespace A; function time(){ echo 'my time function'; } namespace B; function time(){ echo 'my space B time function'; } //只要是namespace B下面的代码都是属于B命名空间不属于A time();//namespace B time() \A\time();//调用A命名空间的time()方法,反斜杠表示根命名空间,所以这里表示根命名空间下面的time()方法 \B\time();//也可以用这种方式来调用B的time方法 echo \time();//全局空间(系统的)的time方法 |
note:
- 如果不使用{}的方式声明命名空间,那么namespace下面就代码这个命名空间的区域,直接调用方法的话调用的就是该命名空间下的方法。
- 可以使用”\”表示根命名空间来调用其他命名空间包括全局空间的方法。
定义命名空间
- 声明单个命名空间 namespace MyProject;
- 定义子命名空间namespace MyProject\Sub\Level;
- 可以在同一个文件中定义多个命名空间
- 可以使用include取引入文件
- 如果没有定义任何命名空间,所有的类与函数的定义都是在全局空间,与PHP引入命名空间概念前一样。
- 在名称前加上前缀\表示该名称是全局空间中的名称,即使该名称为与其他的命名空间中也是如此。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php namespace A\B;//表示A空间下面的B空间 class MyClass { public function __construct() { echo '实例化了<br>'; } } namespace A; class MyClass { public function __construct() { echo '空间A中的类被实例化了<br>'; } } $obj = new MyClass();//A空间 -> 非限定名称 $obj = new \A\B\MyClass();//A空间下的B空间 ->完全限定名称 从根空间截取的 $obj = new \A\MyClass();//根空间中的A空间,其实就是A空间 ->完全限定名称 $obj = new B\MyClass();//类似于相对路径的写法,现在是A空间,A空间下面的B空间 ->限定名称 相对路径的写法 |
__namespace__常量
- 包含了当前命名空间名称的字符串
- 在全局的,不包括在任何命名空间的代码,它包含一个空的字符串
- 使用include调用命名空间不会引起当前命名空间的改变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php namespace A\B;//表示A空间下面的B空间 class MyClass { public function __construct() { echo '实例化了<br>'; } } echo __NAMESPACE__; echo '<hr>'; namespace A; class MyClass { public function __construct() { echo '空间A中的类被实例化了<br>'; } } echo __NAMESPACE__; $obj = new MyClass(); |
命名空间和动态语言特征
动态里访问命名空间的元素
- $a = ‘\namespacename\classname’;
- $obj = new $a;
- $a = ‘namespacename\classname’;
- $obj = new $a;
- $b = ‘namespacename\function’;
- $b();
- $b = ‘\namespacename\function’;
- $b();
- 注意:限定名称和完成限定名称的结果是一样的。
动态访问命名空间的元素
- 必须使用完全限定名称(包括命名空间前缀的类的名称)。
- 注意:因为在动态的类名称、函数名称或者常量名称中,限定名称和完全限定名称没有区别,因此其前面的反斜杠是不必要的。
1 2 3 4 5 6 7 |
<?php function test(){ echo 'test function'; } $a='test'; $a();//以动态语言的方式调用 |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php namespace A\B; function test(){ echo 'test function'; } namespace A; $a='\A\B\test'; $a();//以动态语言的方式调用 // 完全限定名称 第一个 \ 不必要 $a = 'A\B\test'; $a(); |
使用命名空间:别名/导入
- 允许通过别名引用或导入外部的完全限定名称,是命名空间的一个重要特征。
- 支持三种别名或导入方式:为类名称使用别名、为接口使用别名或为命名空间名称使用别名。
- PHP 5.6 开始允许导入函数或常量或者为它们设置别名
通过操作符use来实现
namespace foo;
use My\Full\Classname; //导入
use My\Full\NSname as MyNS; //别名导入
use My\Full\Classname as Another, My\Full\Nsname
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<?php function myLoader($name) { echo '加载的类为:'.$name; exit(); } spl_autoload_register('myLoader',true,true); // 导入 空间 完全限定名称 不要第一个\ // use A\B\C\MyClass; // $obj = new MyClass(); //导入多个 // use A\B\C\MyClass,C\D\Test; // $obj = new Test(); // 导入多个并且取别名as use A\B\C\MyClass,C\D\E\Test as T; // 实例化 导入类 // $obj = new T(); // 空间方式使用 导入 空间 // $obj = new T\MyClass(); // 接口方式使用 导入借口哦 // class Person implements T // { // } // PHP5.6之后可以导入函数或常量或者为他们设置别名 // 导入函数 include '8_1.php'; use function A\S\D\func; func(); // 导入常量 use const A\S\D\NUM; echo NUM; // 别名 use function A\S\D\func as xx; xx(); // 注意:不能连在一起导入多个,只能一个个的去导入。 |
8_1.php
1 2 3 4 5 6 7 8 9 10 |
<?php namespace A\S\D; function func() { echo 'namespace A\S\D function func() <br>'; } CONST NUM = 123; |