命名空间概述

PHP的命名空间在PHP5.3之后的版本才有

什么是命名空间?从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。具体举个例子,文件 foo.txt 可以同时在目录/home/greg 和 /home/other 中存在,但在同一个目录中不能存在两个 foo.txt 文件。另外,在目录 /home/greg 外访问 foo.txt 文件时,我们必须将目录名以及目录分隔符放在文件名之前得到 /home/greg/foo.txt。这个原理应用到程序设计领域就是命名空间的概念。

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

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

PHP 命名空间提供了一种将相关的类、函数和常量组合到一起的途径。

问题1示例:我们在目录Mytest下建立一个类文件TestClass.php,申明类:TestClass.php,然后在index.php里面使用,只要有包含就可以能够正常使用,我们看示例A

示例A:

目录结构

Mytest  //目录名
    --index.php  //Mytest目录下index.php文件,客户端文件
		--TestClass.php  //Mytest目录下TestClass.php文件,类申明文件

TestClass.php内容:

<?php 
class TestClass {

		public function getClassName()
		{
				echo __CLASS__;
		}
}

index.php文件内容:

<?php 
require_once 'Test.php';
$testClass = new Mytest\TestClass;
$testClass->getClassName();

结果输出:

getFunctionName

同样是问题1,假如我们项目比较大,有很多的类,这样我们就必须保证在一个文件里面调用的类,必须是绝对不重名的,如果有N个人协同开发,你必须保证所有人都能够做到所有的类命名,常量等不重复,想想有多困难。如果做不到就像这样。

我们在示例A的目录结构下,增加一个子目录MytestSub,在子目录里面有一个TestClass.php,申明一个类TestClass.php

示例A新目录如下:

注意:如果是类文件,类名与文件名一致

Mytest  //目录名
    --index.php  //Mytest目录下index.php文件,客户端文件
		--TestClass.php  //Mytest目录下TestClass.php文件,类申明文件
		--MytestSub  //Mytest目录下子目录
		       --TestClass.php   //Mytest目录下子目录MytestSub目录下文件

假设我们需要在同一个文件中调用到这两个类,看下面示例:

MytestSub目录下TestClass.php文件内容(仅作示范,主要是为了申明类名冲突)

<?php 
class TestClass {

		public function getClassName()
		{
				echo __CLASS__;
		}
}

客户端调用代码:

<?php 
require_once 'TestClass.php';
require_once 'MytestSub/TestClass.php';
$testClass = new TestClass;
$testClass->getClassName();
$testClass = new TestClass;
$testClass->getClassName();

结果:

Fatal error: Cannot redeclare class TestClass

这就是命名冲突的问题,当项目足够大,开发人员较多的时候,你无法保证所有人的命名不会冲突。

同样,我们看第二个问题,假如我在上述增加了子目录的时候,每个人都遵循规范,我在子目录里面申明的类不是命名为TestClass,我加上目录,命名为:MytestSubTestClass,这样的话不就可以保证命名不冲突了吗?一个目录下的文件名总是有限的,但是如果目录有三层呢,四层呢,甚至更多,你的类名就会变得很长,开发的时候看类名就已经够了,心好累哈哈。

我们再看下,使用了命名空间的示例

先看问题1的:

Mytest目录下TestClass.php文件内容:

<?php 
namespace Mytest; //申明命名空间
class TestClass {

		public function getClassName()
		{
				echo __CLASS__;
				echo '<br>';
		}
}

Mytest目录下子目录MytestSub目录下TestClass.php文件内容:

<?php
namespace Mytest\MytestSub; //申明命名空间
class TestClass {

		public function getClassName()
		{
				echo __CLASS__;
		}
}

客户端调用代码:

<?php 
require_once 'TestClass.php';
require_once 'MytestSub/TestClass.php';
$testClass = new Mytest\TestClass;
$testClass->getClassName();
$testClass = new Mytest\MytestSub\TestClass;
$testClass->getClassName();

结果:

Mytest\TestClass
Mytest\MytestSub\TestClass

这样命名冲突问题就可以解决了,只要不在同一个命名空间内,无论重复多少个类名都无所谓。

我们再看问题2,我觉得$testClass = new Mytest\MytestSub\TestClass;这么调用太长了,要写好长的代码,那么你可以这样,我们看示例:

<?php
use Mytest\MytestSub\TestClass as ShortClass;  //使用别名
require_once 'TestClass.php';
require_once 'MytestSub/TestClass.php';
$testClass = new Mytest\TestClass;
$testClass->getClassName();
$testClass = new ShortClass;  //直接使用别名
$testClass->getClassName();

结果:

Mytest\TestClass
Mytest\MytestSub\TestClass

PHP中引入命名空间主要是为了解决这两个问题,深入学习可以看后面的教程:PHP命名空间(二)-定义命名空间