前言
假设我们有 Tools/A/Foo.php 、Tools/B/Foo.php
文件,这两个 Foo.php
定义了同一个类,然后从 C.php
引入这两个文件,大家说会出现什么情况?代码如下
# Tools/A/Foo.php
class Foo{
public function __construct() {}
public function say() {
echo "Hello,world";
}
}
# Tools/B/Foo.php
class Foo{
public function __construct() {}
public function say() {
echo "Hello, Tony";
}
}
# C.php
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 我们来调整一下结构
# Tools/A/Foo.php
class A_Foo{ # 将 Foo 改为 A_Foo
// 代码不变
}
# Tools/B/Foo.php
class B_Foo{ # 将 Foo 改为 B_Foo
// 代码不变
}
# C.php
include_once "Tools/A/Foo.php";
include_once "Tools/B/Foo.php";
$a = new A_Foo();
$a->say(); // Hello,world
$b = new B_Foo();
$b->say(); // Hello,Tony
看似问题是解决了,但还面临着其它情况
- 引入第三方插件时,名字也可能冲突
- 若目录嵌套过深,独立前缀加长,使用时也要跟着加长,可读性差
- 团队开发各个成员也容易遇到出现命名重复问题
就算能解决以上这3个问题,每个人的处理方式终究不一样,只会让维护性更差。
说到底还是缺少一种规范,这不 PHP 就新出了 namespace
命名空间这玩意,大家都只要按照它的语法来写问题就迎刃而解。
namespace
好处
- 解决命名重复问题
- 统一规范,各个文件类名依然可以保留,不再需要单独写 _ 下划线进行兼容。
用法
假设我们的目录结构如下
Tools
A
Foo.php
B
Foo.php
C.php
# Tools/A/Foo.php
namespace Tools\A; # 新增
class Foo{
// 内容不变
}
# Tools/B/Foo.php
namespace Tools\B; # 新增
class Foo{
// 内容不变
}
# C.php
include_once "Tools/A/Foo.php";
include_once "Tools/B/Foo.php";
$a = new Tools\A\Foo();
$a->say(); // Hello,world
$b = new Tools\B\Foo();
$b->say();// Hello,Tony
我们可以看到,两个文件的类名依然一样,只需 new 时带上 namespace
定义的前缀即可,可能有的小伙伴就疑惑了?这种写法不是跟 _ 下划线差不多吗?
注意:还是有差别的,各自文件的类名 Foo
依然保持一致不是吗?
可能你觉得总差点东西,对,名字过长的问题怎么解决? 别急,这不还有另外一个语法 use
,我们来改动一下 C.php
代码
# 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(); // Hello,world
$b = new Foo2();
$b->say();// Hello,Tony
现在既保持源类名相同,又能通过 use 方式来简化语法,问题迎刃而解。
对于 PHP 开发者来说掌握 namespace
语法是必须不可缺的。
不知道你注意没有?案例中每次都要通过 include_once
方式引入文件,有没有很繁琐?
另外,使用 namespace
也是有规范的,不能随便就定义自己的前缀,通常需要以你的父目录作为前缀,想要了解更多可以参考我写过的:PHP & 理解 autoload 、PSR-0、PSR-4 的因缘并分析 PS0-0 与 PSR-4 的差异到底在哪里