简介

文档:PHP 手册 - 命名空间

从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。

简单来说,解决类,函数的重名问题,相当于电脑的文件夹。

例如:另外,在目录 /a/b 外访问 aa.php 文件时,我们必须将目录名以及目录分隔符放在文件名之前得到 /a/b/aa.php ,这个原理应用到程序设计领域就是命名空间的概念。

图例:
文件 aa.php 可以同时在目录 a/ba/c 中存在,
image.png

但在同一个目录中不能存在两个 aa.php 文件。
image.png

解决了什么问题

命名空间可以用来解决在编写「类库」或「应用程序」时创建可重用的代码如类或函数时碰到的两类问题:

  • 用户编写的代码与PHP内部的 类/函数/常量 或 第三方类/函数/常量 之间的名字冲突。
  • 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。

注意

  1. 在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句。另外,所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前

  2. 命名空间的分隔符是反斜杠 \ , 不是 /

  3. 多数框架中,命名空间路与文件夹路径需要一致

  4. 命名空间一般与实际文件夹对应


  1. 实际开发中不建议一个文件内写多个命名空间

语法

定义命名空间

命名空间通过关键字「namespace」来声明。
如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间,除了一个 declare 关键字以外。

  1. namespace mya;
  2. class a{
  3. function aa(){
  4. return '我在命名空间 mya 下';
  5. }
  6. }
  7. var_dump(new a()); //输出:object(mya\a)#1 (0) { }

输出:命名空间为 mya
image.png

定义子命名空间

namespace mya\myb;

class a{ 
    function aa(){
        return '我在命名空间 mya 下';
    }
 }

var_dump(new a()); //输出:object(mya\myb\a)#1 (0) { }

输出:命名空间为 mya/myb
image.png

在同一个文件夹下定义多个命名空间

注意:在实际的编程实践中,非常不提倡在同一个文件中定义多个命名空间。这种方式的主要用于将多个 PHP 脚本合并在同一个文件中。

有两种定义的语法

第一种(不推荐):定义多个命名空间,简单组合语法

不建议使用这种语法,建议使用下面那种语法

namespace mya;

class a{ 
    function aa(){
        return '我在命名空间 mya 下';
    }
 }

var_dump( new a() ); //输出:object(mya\a)#1 (0) { }

namespace myb;

class a{ 
    function aa(){
        return '我在命名空间 mya 下';
    }
 }

var_dump( new a()); //输出:object(myb\a)#1 (0) { }

第二种(推荐):定义多个命名空间,大括号语法

namespace mya{
    class a{ 
        function aa(){
            return '我在命名空间 mya 下';
        }
    } 
}

var_dump( new a() ); //输出:object(mya\a)#1 (0) { }

namespace myb{
    class a{ 
        function aa(){
            return '我在命名空间 mya 下';
        }
    }
}

var_dump( new a()); //输出:object(myb\a)#1 (0) { }

使用命名空间

在使用命名空间之前,必须了解 PHP 是如何知道要使用哪一个命名空间中的元素的。

相对路径:直接输入子命名空间,以当前代码所在命名空间计算

绝对路径:以 \ 开头的完整路径, use 无须 / ,默认就是绝对路径

可以将 PHP 命名空间与文件系统作一个简单的类比。在文件系统中访问一个文件有三种方式:

  1. 相对文件名形式如 foo.txt 。它会被解析为 currentdirectory/foo.txt,其中 currentdirectory 表示当前目录。因此如果当前目录是 /home/foo,则该文件名被解析为 /home/foo/foo.txt 。

  2. 相对路径名形式如 subdirectory/foo.txt 。它会被解析为 currentdirectory/subdirectory/foo.txt 。

  3. 绝对路径名形式如 /main/foo.txt 。它会被解析为 /main/foo.txt 。

namespace mya\a;

    class a{ 
        function aa(){
            return '我在命名空间 mya\a 下';
        }
    } 


namespace mya\b;
    class a{ 
        function aa(){
            return '我在命名空间 mya\b 下';
        }
    } 

    //非限定名称
    var_dump( new a() ) ;

    //完全限定名称
    var_dump( new \mya\a\a() );

输出:
图片.png


导入/别名 (use / as)

use = 载入指定命名空间 , use 无须 / ,默认就是绝对路径

as = 别名,起一个别名,方便调用

namespace my\a\k{
    class a{ 
        function aa(){
            return '我在命名空间 mya\a 下';
        }
    } 
    var_dump( new a() ) ;
}

//导入
namespace my\b\kk{
    //导入
    use my\a\k\a;

    class b{ 
        function bb(){
            return '我在命名空间 mya\b 下';
        }
    } 

    var_dump( new a() ) ;
}

//导入并重命名
namespace my\b\kk{

    //导入并重命名
    use my\a\k\a as ww;

    class b{ 
        function bb(){
            return '我在命名空间 mya\b 下';
        }
    } 

    var_dump( new ww() ) ;
}