2017新手学习框架必备:Thinkphp5框架教程之命名空间详解
命名空间
ThinkPHP采用命名空间方式定义和自动加载类库文件,有效的解决了多模块和Composer类库之间的命名空间冲突问题,并且实现了更加高效的类库自动加载机制。
可以移步至我们课程:弹指间学会PHP编程之命名空间教程
我们也提供了相关视频课程:独孤九贱(5)_ThinkPHP5视频教程
由于PHP语法里不支持函数重载机制,如果一个应用里有两个同名的方法,怎么办?在Yii框架为了避免名字重复引起问题,全部的类前边都有 C 字样,而在ThinkPHP里就引入了命名空间这个概念。其中有几点需要特别注意:
a) 命名空间是虚拟的定义空间,不是真实存在目录
b) 命名空间的分隔符都是反斜杠 \
c) 命名空间只对函数,类,常量(const定义的常量,非define定义的常量)有效。
d) 命名空间有三种访问方式:非限定名称访问方式;限定名称访问方式;完全限定名称访问方式。
接下来就一一详细说明。
一、命名空间只对函数,类,常量(const定义的常量,非define定义的常量)有效。
这里我们声明了两个命名空间space1和space2,两个命名空间下面有同名的函数getmsg(),同名的常量a,同名的类Animal,因为它们处于不同的命名空间下,所以不会产生错误。我们在浏览器中打开,得到如下输出:helloworld。
如果我们尝试用define定义两个同名常量呢?
浏览器中打开报如下错误:
所以命名空间只对函数,类,常量(const定义的常量,非define定义的常量)有效。
二、多级命名空间和三种访问方式
上面声明的命名空间space1和space2都是单级命名空间,形如 space1\space2\space3的命名空间为多级命名空间,分隔符为\。下面介绍三种命名空间访问方式:
1、非限定名称访问方式
当以非限定名称访问方式访问时,访问的是当前命名空间下的函数(类和常量同理),所以以上代码输出结果是:world。
2、完全限定名称访问方式
如果想要在 name2\space2 命名空间下访问 name1\space1下的getmsg()方法,可以使用完全限定名称访问方式(相当于绝对路径访问)。
所以上述代码的输出结果为:hello。
3、限定名称访问方式
限定名称访问方式与完全限定名称访问方式差别只在最前面的\。如果上例使用限定名称访问方式访问,则将最后一行改为:name1\space1\getmsg();
此时,我们在浏览器中打开,发现如下错误:
提示我们无法找到命名空间 name2\space2\name1\space1 下的 getmsg() 函数。原因是限定名称访问方式相当于相对路径访问,我们在当前命名空间下使用限定名称访问方式访问:name1\space1\getmsg(),会在当前命名空间下寻找name1\space1下的getmsg()函数,找不到就会报错。所以,如果我们再声明一个名为: name2\space2\name1\space1 的命名空间,上述访问就可以正常执行,如下:
输出结果为:hello-world。
三、命名空间和空间类元素的引入机制
1、引入命名空间
通过上面的例子,我们可以看到如果想要在当前命名空间下使用另一个命名空间下的函数、常量或者类元素的时候,我们需要使用完全限定访问方式进行访问,写代码比较繁琐,所以,我们可以引入命名空间,然后使用限定名称访问方式进行访问,简化访问过程。
输出结果为:hello dog
2、引入空间类元素
与命名空间的引入方式类似,使用 use 关键字引入空间类元素,然后直接使用非限定访问方式进行访问即可。不过,在当前命名空间下不能存在与引入类同名的类,否则会产生错误。
输出结果为:dog大黄。
四、公共空间
如果我们没有使用 namespace 关键字声明命名空间,则其属于公共空间。
这里我们建立两个php文件,1.php 和 2.php,1.php命名空间为 name1\space1, 2.php为公共空间。
1.php:
namespace name1\space1; header("content-type:text/html;charset=utf-8"); class Animal { public $obj = 'dog'; static $name = '大黄'; } function getmsg() { echo 'hello'; } const MN = 123; //在命名空间中引入公共命名空间 include ('./2.php'); getmsg(); //访问的是当前空间下的getmsg()函数 echo '</br>'; \getmsg(); //访问的是公共命名空间(即2.php文件)下的getmsg()函数 echo '</br>'; echo MN; //会先在当前命名空间下寻找MN常量,如果找到就输出,如果找不到,就会去公共命名空间寻找MN常量 echo '</br>'; echo \MN; //访问的是公共命名空间(即2.php文件)下的MN常量
2.php:
//没有指定命名空间,则其属于公共命名空间 function getmsg() { echo 'world'; } const MN = '456';
浏览器中打开1.php,输出结果为:
hello
world
123
456
五、 命名空间是虚拟的定义空间,不是真实存在目录
在thinkphp5.0中,命名空间是虚拟的定义空间,不是真实存在目录。只不过是官方在声明命名空间时,命名空间的名称刻意与目录结构有对应关系。
例如,我们打开 application/index/controller 文件夹下的 Index.php 文件,其命名空间为:app\index\controller。在目录结构中并不存在。
命名空间别名
框架允许给命名空间定义别名,例如:
namespace app\index\model; use think\Model; class User extends Model { }
原来在控制器里面调用方式为:
namespace app\index\controller; use app\index\model\User; class Index { public function index() { $user = new User(); } }
如果我们在应用公共文件中注册命名空间别名如下:
\think\Loader::addNamespaceAlias('model','app\index\model');
那么,上面的控制器代码就可以更改为:
namespace app\index\controller; use model\User; class Index { public function index() { $user = new User(); } }
相关资料推荐: