PHP命名空间类似于操作系统中的目录,如在D盘不能存在两个同名的文件,但是可以先创建两个不同名称的文件夹,然后将两个同名的文件,分别放到两个不同的文件夹中,就没有问题了。这里的目录就相当于命名空间。
一旦将文件放入文件夹中,在访问此文件时,就必须加路径中加入此文件夹的名称,如 D:\1219\psb.jpg
PHP中也不允许出现两个重名的类、函数或者常量,否则会产生一个致命错误。
name=$name;
}
}
class Student{
public $age;
public function __construct($age)
{
$this->age=$age;
}
}
$s=new Student("参数");
运行代码
Fatal error: Cannot declare class Student, because the name is already in use in D:\phpStudy\WWW\test\test.php on line 9
为了避免重名,除了可以在名称前面加上前缀之外,更加推荐的方法就是使用命名空间,将相同名称的类、函数或者常量放到不同的命名空间中。
创建命名空间使用 namespace 关键字,上面的问题通过如下改造就不会报错了
namespace blog1;
class Student{
public $name;
public function __construct($name)
{
$this->name=$name;
}
}
namespace blog2;
class Student{
public $age;
public function __construct($age)
{
$this->age=$age;
}
}
$s=new Student("参数");
echo $s->age;
上面代码创建了两个命名空间,名称分别为blog1和blog2。
注意每个命名空间的范围:命名空间的范围是从定义语句开始一直到下一个命名空间定义语句结束。
所以下面的代码仍然处于命名空间blog2中,所以这里的Student使用的是blog2下的Student
$s=new Student("参数");
如果想使用blog1中的Student类,就要使用下面的语法, \命名空间 名称\元素名称
$s=new \blog1\Student("参数");
echo $s->name;
思考:为什么这么写?
因为当前还在blog2空间下,要使用其他空间的类,就只能这么写
命名空间中,除了类,还可以拥有常量和函数,使用方法与类是一样的,这里不再赘述
全局空间也成为公共空间,即不属于我们定义的任何一个空间,公共空间的类、方法和常量,在任何一个命名空间中都可以使用。
上面用于访问另一个空间的符号“\”,也可用于访问全局空间元素
如下面代码在自己的命名空间中定义了一个与系统函数重名的函数,如果想使用系统的函数,就必须使用“\”
namespace blog3;
//如果不将此函数定义到blog3命名空间中,会报错的,因为与系统函数名称冲突
function var_dump($data){
echo $data;
}
//这里调用的是blog3命名空间中的var_dump函数
var_dump("hello");
echo "
";
//这里调用的是系统的函数
\var_dump("hello");
除了系统函数属于全局空间,我们自定义的函数,如果不属于任何空间,也属于公共空间
新建 common.php,编写如下代码
function say($data){
echo "hello".$data;
}
然后在其他文件中引入此文件,并调用 say 函数
require_once 'common.php';
\say("小明");
说明:也可以不使用“\”,但是为了规范,建议还是加上
在文件系统中,一个目录下面还可以有目录,命名空间也是如此,命名空间下面还可以空间,叫做子空间
子空间是在实际的项目需求中需要的,这点MVC时就会看到
namespace blog4;
namespace blog4\controller;
function f1(){
echo "blog4\controller";
}
namespace blog4\model;
function f1(){
echo "blog4\model";
}
namespace blog\view;
function f1(){
echo "blog4\\view";
}
//调用命名空间 blog4\view
f1();
//调用命名空间 blog4\controller
\blog4\controller\f1();
//调用命名空间 blog4\model
\blog4\model\f1();
这里要说明的如何使用其他命名空间中的类、函数和常量,换句话说就是如何使用路径
就是在使用类等元素时不使用前缀,而是直接使用元素名称,如类名、函数名称、常量名称
namespace blog1;
class beauty{
public function __construct()
{
echo "beauty";
}
}
/**
* 在当前命名空间下使用本空间的类,可以直接使用类的名称
* 前面不需要加入命名空间前缀
*/
$b=new beauty();
包含前缀的名称,类似于相对路径,是相对于当前的命名空间定位的,主要适合于使用当前命名空间的子空间中的类等元素。
新建一个文件,命名为namespace.php
namespace blog1\controller;
class beauty{
public function __construct()
{
echo "controller/beauty";
}
}
然后在父空间所在目录编写如下代码
namespace blog1;
class beauty{
public function __construct()
{
echo "beauty";
}
}
require_once './namespace.php';
/**
* 在当前命名空间下使用子空间中的类,需要在类名前面加上子空间名称前缀
* 最终的路径如下 blog1\controller\beauty
*/
$b=new controller\beauty();
包含了全局前缀操作符,相当于绝对路径
比如上面的代码,使用子空间中的类时,还可以写成这样
$b=new \blog1\controller\beauty();
注意,完全限定名称与限定名称之间的区别在于前面是否加上“\”操作符
使用完全限定名称最主要的作用还是使用其他命名空间中的元素。
在namespace.php 中加入如下代码
namespace blog2;
class Beauty{
public function __construct()
{
echo "blog2\beauty";
}
}
在当前文件中编写如下代码
class beauty{
public function __construct()
{
echo "beauty";
}
}
require_once 'namespace.php';
$s=new \blog2\Beauty();
如果我们使用的类不再当前的命名空间下,则在使用类的名称时要加入前缀,如上面的最后一行代码。
导入命名空间可以看作是调用其他命名空间元素的一种快捷方式,可以省略前缀
如修改上面的部分代码
require_once 'namespace.php';
/**
* 导入命名空间blog2,
* 使用User类时可以省却前面的“\”
*/
use blog2;
$s=new blog2\User();
也可以直接导入其他空间中的类,这样使用类时可以直接编写类名,而不在使用前缀
require_once 'namespace.php';
/**
* 导入命名空间blog2中的Userl类,
* 使用User类时可以省却前面的所有前缀
*/
use blog2\User;
$s=new User();
如果导入的类名在当前命名空间中存在,则会报错
解决方法就是为其设置别名
require_once 'namespace.php';
/**
* 如果导入的命名空间中的类与当前命名空间中的类重名,
* 则可以为其设置别名
*/
use blog2\beauty as B;
$s=new B();
说明:PHP并不支持导入函数或常量