前言
假设我们有 Tools/A/Foo.php 、Tools/B/Foo.php 文件,这两个 Foo.php 定义了同一个类,然后从 C.php 引入这两个文件,大家说会出现什么情况?代码如下
class Foo{
public function __construct() {}
public function say() {
echo "Hello,world";
}
}
class Foo{
public function __construct() {}
public function say() {
echo "Hello, Tony";
}
}
include_once "Tools/A/Foo.php";
include_once "Tools/B/Foo.php";
$foo = new Foo();
$foo->say();
你会看到报如下错误: Fatal error: Cannot declare class Foo, because the name is already in use
该错误表示 Foo 已经重复声明过了,解决方式也很简单,我们拼接独立的前缀不就行了,so 我们来调整一下结构
class A_Foo{
}
class B_Foo{
}
include_once "Tools/A/Foo.php";
include_once "Tools/B/Foo.php";
$a = new A_Foo();
$a->say();
$b = new B_Foo();
$b->say();
看似问题是解决了,但还面临着其它情况
- 引入第三方插件时,名字也可能冲突
- 若目录嵌套过深,独立前缀加长,使用时也要跟着加长,可读性差
- 团队开发各个成员也容易遇到出现命名重复问题
就算能解决以上这3个问题,每个人的处理方式终究不一样,只会让维护性更差。 说到底还是缺少一种规范,这不 PHP 就新出了 namespace 命名空间这玩意,大家都只要按照它的语法来写问题就迎刃而解。
namespace
好处
- 解决命名重复问题
- 统一规范,各个文件类名依然可以保留,不再需要单独写 _ 下划线进行兼容。
用法
假设我们的目录结构如下
Tools
A
Foo.php
B
Foo.php
C.php
namespace Tools\A;
class Foo{
}
namespace Tools\B;
class Foo{
}
include_once "Tools/A/Foo.php";
include_once "Tools/B/Foo.php";
$a = new Tools\A\Foo();
$a->say();
$b = new Tools\B\Foo();
$b->say();
我们可以看到,两个文件的类名依然一样,只需 new 时带上 namespace 定义的前缀即可,可能有的小伙伴就疑惑了?这种写法不是跟 _ 下划线差不多吗? 注意:还是有差别的,各自文件的类名 Foo 依然保持一致不是吗? 可能你觉得总差点东西,对,名字过长的问题怎么解决? 别急,这不还有另外一个语法 use ,我们来改动一下 C.php 代码
include_once "Tools/A/Foo.php";
include_once "Tools/B/Foo.php";
use Tools\A\Foo as Foo1;
use Tools\B\Foo as Foo2;
$a = new Foo1();
$a->say();
$b = new Foo2();
$b->say();
现在既保持源类名相同,又能通过 use 方式来简化语法,问题迎刃而解。 对于 PHP 开发者来说掌握 namespace 语法是必须不可缺的。
|