前言
在我看来,namespace的出现主要是为了解决名称冲突(包括类名冲突、方法名冲突等)以及缩短一些很长的标识符名称(增强可读性)。namespace的思想就类似我们系统中的文件夹。
废话不多说,直接进入正文。
声明方式
namespace有两种声明方式
第一种,其中 FirstClass 属于firstNameSpace的命名空间,SecondClass属于secondNameSpace的命名空间
namespace firstNameSpace;
class FirstClass{
}
namespace secondNameSpace;
class SecondClass{
}
第二种,个人比较推荐使用第二种,其中 ThirdClass属于thirdNameSpace的命名空间,FourthClass属于fourthNameSpace的命名空间
记住第二种方法中namespace末尾可以不用加分号,
namespace thirdNameSpace{
class ThirdClass{
}
}
namespace fourthNameSpace{
class FourthClass{
}
}
小提醒:如果你的代码使用了namespace,那么当前文件中所有的代码都必须包括在namespace中,如下代码会报错
namespace thirdNameSpace{
class ThirdClass{
}
}
namespace fourthNameSpace{
class FourthClass{
}
}
echo 'Hello NameSpace';
修改方法:把最后一句中的
echo 'Hello NameSpace';
单独放在一个全局的命名空间中(全局命名空间可以忽略空间名),如下
namespace thirdNameSpace{
class ThirdClass{
}
}
namespace fourthNameSpace{
class FourthClass{
}
}
namespace {
echo 'Hello NameSpace';
}
第三个命名空间就是全局的命名空间,至于全局空间的导入,下面会讲。
使用方式
在这里,我分成三个情况来讲解
一、同个文件中使用namespace
①非限定名称方式:
字面上理解,就是不用指定名称的方式,看代码就懂了
namespace app{//假设有一个app的命名空间
const NAME = '管理员';//定义一个NAME为管理员的常量
function returnFunctionName(){//定义一个返回方法名称的方法
return __FUNCTION__;
}
echo '这里是'.NAME.'<br>';//非限定名称:可以省略命名空间,直接访问常量NAME
echo '这个方法是'.returnFunctionName().'<hr>';//方法也是如此,可以直接访问
}
其中要使用常量NAME,可以直接在命名空间app中,使用NAME,即可访问,同理app中的方法也是如此。
②限定名称方式:
在讲限定名称方式之前,先给大家讲一个概念:子命名空间
顾名思义,子命名空间与“父”命名空间的关系 就类似 子类与父类的关系
一开始提到,命名空间的思想就类似我们系统中的文件夹,想象一下,我们在系统存放一个视频的时候
一般都是存放与文件夹中,然后可能文件夹中放着文件夹,一层一层的展开,最后可能放了我们某个学习资料.avi
子命名空间就类似文件夹
如果我们把一个学习资料.avi存在D:/php/study/中,那我们要打开这个视频,就需要访问以D盘为根目录,D盘中的php为子文件夹,然后里面再有个study的子文件夹,最后再是我们的视频
同理,如果我们想在app为根命名空间,app中的index中的user为子命名空间,存放一个study的方法
那我们可以这么写
namespace app\index\user {//假设有一个app\index\user的命名空间
const USERNAME = 'Student';//定义一个值为Student的常量USERNAME
function study(){//定义一个study的方法
echo 'I am studying';
}
}
如果,在app\index里面有另外一个命名空间admin,存放了一个manage的方法
那我们可以这么写
1.php
namespace app\index\user {//假设有一个app\index\user的命名空间
const USERNAME = 'Student';//定义一个值为Student的常量USERNAME
function study(){//定义一个study的方法
return 'I am studying';
}
}
namespace app\index\admin {//假设有一个app\index\admin的命名空间
const USERNAME = 'Admin';//定义一个值为Admin的常量USERNAME
function manage(){//定义一个manage的方法
return 'I am managing';
}
}
注意两个命名空间都位于同一个文件中
app\index\user命名空间中有一个study()方法,app\index\admin命名空间有一个manage()方法
在app\index中就有两个子命名空间,一个是user,一个是admin,可以联想系统文件夹
接下来进入正题
字面上理解,限定名称方式就是要使用指定名称的方式,
如果想要在app\index的命名空间中访问user中的study方法,以及admin中的manage方法,如下
1.php
namespace app\index\student {//假设有一个app\index\student的命名空间
const NAME = 'Student';//定义一个值为Student的常量NAME
function study(){//定义一个study的方法
return 'I am studying';
}
}
namespace app\index\admin {//假设有一个app\index\admin的命名空间
const NAME = 'Admin';//定义一个值为Admin的常量NAME
function manage(){//定义一个manage的方法
return 'I am managing';
}
}
namespace app\index {//命名空间为app\index
echo 'NAME is '.admin\NAME.'<br>';//访问当前命名空间app\index中的admin子命名空间中的常量NAME
echo 'And '.admin\NAME.' say: '.admin\manage().'<br><br>';//访问当前命名空间app\index中的admin子命名空间中的方法manage
echo 'NAME is '.student\NAME.'<br>';//访问当前命名空间app\index中的student子命名空间中的常量NAME
echo 'And '.student\NAME.' say: '.student\study().'<hr>';//访问当前命名空间app\index中的student子命名空间中的方法study
}
在第三个命名空间中,指定了第三个命名空间为app\index
要使用admin中的NAME,则可以直接admin\NAME,同理,student\NAME可以访问student中的NAME常量
这种思想可以理解为在指定一个命名空间中,使用相对的子命名空间
以上这种方式,成为限定名称方式,通常用于子空间中
③完全限定名称方式:
跟第二种类似,第三种方式为“绝对路径”,即从根命名空间开始,看代码
1.php
namespace app\index\student {//假设有一个app\index\student的命名空间
const NAME = 'Student';//定义一个值为Student的常量NAME
function study(){//定义一个study的方法
return 'I am studying';
}
}
namespace app\index\admin {//假设有一个app\index\admin的命名空间
const NAME = 'Admin';//定义一个值为Admin的常量NAME
function manage(){//定义一个manage的方法
return 'I am managing';
}
}
namespace app\index {//命名空间为app\index
echo 'NAME is '.admin\NAME.'<br>';//访问当前命名空间app\index中的admin子命名空间中的常量NAME
echo 'And '.admin\NAME.' say: '.admin\manage().'<br><br>';//访问当前命名空间app\index中的admin子命名空间中的方法manage
echo 'NAME is '.student\NAME.'<br>';//访问当前命名空间app\index中的student子命名空间中的常量NAME
echo 'And '.student\NAME.' say: '.student\study().'<hr>';//访问当前命名空间app\index中的student子命名空间中的方法study
}
namespace {
echo 'NAME is '.app\index\admin\NAME.'<br>';//使用完全限定名称访问app\index\admin中的NAME常量
echo 'And '.app\index\admin\NAME.' say: '.app\index\admin\manage().'<br><br>';//使用完全限定名称访问app\index\admin中的manage方法
echo 'NAME is '.app\index\student\NAME.'<br>';//使用完全限定名称访问app\index\student中的NAME常量
echo 'And '.app\index\student\NAME.' say: '.app\index\student\study().'<hr>';//使用完全限定名称访问app\index\student中的study方法
}
第四个命名空间为全局的命名空间,在这个空间中
使用app\index\admin\NAME来访问app\index\admin中的NAME常量
使用app\index\admin\manage()来访问app\index\admin中的mange()方法
同理,student命名空间的调用也是如此。
二、不同个文件中使用namespace
假设要在2.php中,使用1.php中的app\index\admin命名空间
则必须在2.php中先include或者require1.php
include '1.php';
echo 'NAME is '.app\index\admin\NAME.'<br>';//使用完全限定名称访问app\index\admin中的NAME常量
echo 'And '.app\index\admin\NAME.' say: '.app\index\admin\manage().'<br><br>';//使用完全限定名称访问app\index\admin中的manage方法
或者
namespace app\index\admin;
include '5_blog.php';
echo 'NAME is '.NAME.'<br>';//使用完全限定名称访问app\index\admin中的NAME常量
echo 'And '.NAME.' say: '.manage().'<br><br>';//使用完全限定名称访问app\index\admin中的manage方法
三、使用use关键字或者use 跟 as搭配
use指定的空间名称,然后用法跟上面的有点小出入,use里面用 子命名空间\常量名 的方式来访问常量
use app\index\admin;
echo 'NAME is '.admin\NAME;
如果觉得admin\NAME这样写比较长,可以使用as作为别名来使用
use app\index\admin as a;
echo 'NAME is '.a\NAME;
一些问题
问题1:全局性函数(php内置函数)的使用
在命名空间中,可以使用与php内置函数相同的名字,比如你可以在app的命名空间中使用strlen来定义一个函数
而且不会报错,代码如下
namespace app{
function strlen($str){//可以定义与内置函数重名的方法
}
}
如果要使用php内置的函数,比如strlen,则需要加一个反斜杠(代表全局的意思),\strlen来表示php内置函数strlen
同理,其它具有全局性的函数(strlen)或者类,都是需要加上反斜杠,类似\strlen,才可以访问指定的函数
namespace app{
function strlen($str){//可以定义与内置函数重名的方法
return \strlen($str);//从php内置函数strlen返回str的长度
}
}
问题2:常量的定义
在上面的例子中,我是使用const来在两个命名空间中定义一个常量,那如果我们使用define来定义呢
namespace app1{
define('A',4);
echo A;
}
namespace app2{
define('A',4);
echo A;
}
出了个小错误,因为define来定义常量具有全局性,在同个文件的两个命名空间中定义两个相同的常量会出错,所以建议使用const来定义命名空间中的常量
Notice: Constant A already defined in
总结
学习没有捷径,如果有不懂的地方,就多打几遍代码,多翻翻官方文档,多琢磨琢磨
我们生活在一个资源丰富的互联网时代,好好利用身边的资源
总有一天,我们也能成为拔尖的人,加油,一起成长