PHP 命名空间详解 (以ThinkPHP举例)

来源:互联网 发布:蚁群算法c语言程序 编辑:程序博客网 时间:2024/05/22 01:32

  摘要:学习TP,要涉及到PHP命名空间的问题,特将学习过程记录如下,给同样入门TP的人铺点路。

  写在最前面的废话,学习PHP,从最初在一个脚本里写出echo “hello world”,到后来需要用include require引入文件来完成中大型项目,当include的文件相当多的时候,函数、类、常量的命名就成了问题,有可能在不同的文件创建相同的函数名,当include进同一个文件的时候,PHP就会出错。PHP使用命名空间的方法来解决这个问题。
  PHP官网对此做了详细讲解:点这里查看
  官网解释非常详细,不过你如果也是入门TP,第一次接触命名空间,先看看我自己总结的办法,也许会有帮助。

一 . 使用传统include文件导致的命名‘撞衫’问题

  先上代码,index.php是我的主文件,里面引用了test.php,两个文件同级。

这是index.php

<?phpinclude 'test.php';function test(){    echo "i am index";}test();?>

这是test.php

<?phpfunction test(){    echo "i am test";}?>

这样引用会导致严重错误,因为PHP解释include语句是替换test.php这个文件进如index.php,很明显一个脚本了里面有两个同名的函数,严重错误!

二 . 使用命名空间改善这一问题

  首先,什么是命名空间,它的作用像是在干什么?
  答:PHP官网上面举这个例子非常好,说我们在文件系统里面放置文件的时候,都知道一个文件夹里面不能出现两个同名的文件,但是两个同名的文件可以放在不同的文件夹下正常使用,因为使用这两个文件的时候,分别有一个绝对路径的地址对他们做了区分。命名空间的原理和它类似,当在项目中为一个文件声明了命令空间,意思就是,这个文件里面的类名、函数名、常量名(都称为元素)是属于这个命名空间(文件夹)的,命令空间可以声明为多层,这样代码之间就会相互隔离,起到了封装的作用。

再来看代码
index.php

namespace Index;include 'test.php';function test(){    echo "i am index";}test();     //这样就调用自己命名空间的test函数Test\test();    //这样就调用了test.php脚本,Index\Test命名空间下的test函数

test.php

namespace Index\Test;function test(){    echo "i am test";}

三 . 命名空间语法规则详述

  先用上面的代码做下解释,有个主观感受:在文件开头,声明namespace,就像是在声明这个文件里的元素所在的“文件夹”,index.php里面的元素位于Index命名空间下,test.php里面的元素位于Index文件夹下的Test文件夹下。那么在index.php文件里面要调用test.php里面的函数的时候,就需要在Index命名空间下使用相对路径Test\test();来引用。
  首先还要了解一下:PHP命名空间元素使用的三种方法:

1.非限定名称,或不包含前缀的类名称,例如 $a=new foo(); 或 foo::staticmethod();。如果当前命名空间是 currentnamespace,foo 将被解析为 currentnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为foo。 警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。详情参见 使用命名空间:后备全局函数名称/常量名称。2.限定名称,或包含前缀的名称,例如 $a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod();。如果当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\subnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为subnamespace\foo。3.完全限定名称,或包含了全局前缀操作符的名称,例如, $a = new \currentnamespace\foo(); 或 \currentnamespace\foo::staticmethod();。在这种情况下,foo 总是被解析为代码中的文字名(literal name)currentnamespace\foo。

  下面还是用代码来说明最常用的语法规则

<?phpnamespace Article;const PATH = '/article';function getCommentTotal() {    return 100;}class Comment { }namespace MessageBoard;const PATH = '/message_board';function getCommentTotal() {    return 300;}class Comment { }//调用当前空间的常量、函数和类echo PATH; ///message_boardecho getCommentTotal(); //300$comment = new Comment();//调用Article空间的常量、函数和类echo \Article\PATH; ///articleecho \Article\getCommentTotal(); //100$article_comment = new \Article\Comment();?>

说明:这里调用Article空间的元素,使用的就是完全限定名称。

别名和导入(很重要)
上代码,然后解释代码

<?phpnamespace Blog\Article;class Comment { }//创建一个BBS空间namespace BBS;//导入一个命名空间use Blog\Article;//导入命名空间后可使用限定名称调用元素$article_comment = new Article\Comment();//为命名空间使用别名use Blog\Article as Arte;//使用别名代替空间名$article_comment = new Arte\Comment();//导入一个类use Blog\Article\Comment;//导入类后可使用非限定名称调用元素$article_comment = new Comment();//为类使用别名use Blog\Article\Comment as Comt;//使用别名代替空间名$article_comment = new Comt();?>

说明:导入命名空间,可以理解为,将要导入的空间复制到当前空间下。
即将Blog\Article这个文件夹复制到BBS文件夹下,那么在BBS空间下,就可以使用限定名称的方式调用Article下的元素了。
或者可以直接导入空间里面的类元素,注意这里:PHP5.6之前的版本只能引入类元素,5.6之后可以引入常量和函数。
当直接导入了类以后,就可以直接使用非限定名称来调用元素了,非常方便!

四 . 以ThinkPHP框架源码来看看命名空间怎么用的

  ThinkPHP版本号:3.2.3
  当第一次启动TP后,PHP会自动建立Home模块,以及子目录

  /Application/Home/Controller/IndexController.class.php

<?phpnamespace Home\Controller;use Think\Controller;class IndexController extends Controller {    public function index(){    }}?>

这里就引用了Think命名空间下的Controller类
这个类的位置在:
/ThinkPHP/Library/Think/Controller.class.php
这个文件里面就使用了
namespace Think;



<完>

1 0
原创粉丝点击