想象你在学校点名:
这就叫:重名冲突。
在 PHP 中,如果两个类都叫 User,就会出错:
class User { } // 用户类
class User { } // 学生类 ❌ 报错!不能重复定义
怎么办?—— 给它们“贴标签”!
命名空间(Namespace)就是给类、函数、常量起“全名”的方式。
比如:
namespace Admin;
class User { } // 全名是:Admin\User
namespace Student;
class User { } // 全名是:Student\User
✅ 现在不会冲突了!一个是“管理员的小明”,一个是“学生的小明”。
<?php
namespace 项目名\模块名\子模块;
class User { }
function login() { }
const VERSION = '1.0';
📌 注意:
<?php 之后)MyApp\Admin\Auth就像公司分部门:
namespace MyProject\User; // 用户部
namespace MyProject\Order; // 订单部
namespace MyProject\Payment; // 支付部
好处:
📁 文件夹建议对应命名空间:
src/
└── User/
└── UserService.php → namespace MyProject\User;
假设你在 MyProject\Order 这个“办公室”里。
| 写法 | 类型 | 含义 | 比喻 |
|---|---|---|---|
User::login() | 非限定 | 找 MyProject\Order\User | “叫小明!”(默认是本部门的) |
User\User::login() | 限定 | 找 MyProject\Order\User\User | “叫用户组的小明!” |
\MyProject\User\User::login() | 完全限定 | 绝对路径,从根找 | “总部三楼的小明!” |
🔁 就像:
- “小明” → 我们部门的小明
- “网络组的小明” → 我们部门里的网络组成员
- “\总公司\技术部\小明” → 绝对地址
如果你覆盖了 PHP 内置函数,想调原始的怎么办?
function strlen($str) { return 0; } // 自己写的
strlen("hello"); // ❌ 调的是自己的
\strlen("hello"); // ✅ 调全局的内置函数
✅ 所有全局类、函数、常量都可以加 `` 调用:
\DateTime::createFromFormat(...);
\Exception("错误");
\INI_ALL;
全名太长?可以用 use 简化:
<?php
namespace MyApp;
use MyProject\Database\Connection as DB;
use function MyProject\Utils\helper as help;
use const MyProject\Config\HOST as SERVER;
// 使用别名
$db = new DB(); // 相当于 new MyProject\Database\Connection
help(); // 相当于 MyProject\Utils\helper()
echo SERVER; // 相当于 MyProject\Config\HOST
📌 use 必须写在 namespace 之后,其他代码之前。
有时候名字是“变量”,比如:
$className = "MyProject\User\User";
$obj = new $className(); // ✅ 可以!
$funcName = "MyProject\help";
$funcName(); // ✅ 可以!
echo constant("MyProject\VERSION"); // ✅ 读常量
在动态调用中:
"MyProject\User" 和 "\MyProject\User" 效果一样__NAMESPACE__ 和 namespace 关键字这是两个“定位工具”,帮你更灵活地写代码。
__NAMESPACE__:GPS 定位器返回当前命名空间的名字(字符串):
namespace MyProject\Order;
echo __NAMESPACE__;
// 输出:MyProject\Order
用途:动态拼类名
$full = __NAMESPACE__ . '\User';
$obj = new $full; // new MyProject\Order\User
namespace 关键字:指南针用来“从当前空间出发”访问元素,类似 self:
namespace\login(); // 调当前空间的 login 函数
namespace\User::find(1); // 调当前空间的 User 类
$obj = new namespace\Order(); // 创建当前空间的 Order 对象
$version = namespace\VERSION; // 获取当前空间的常量
📌 它让你不用写死全名,更安全、更灵活。
PHP 允许,但非常不推荐!
<?php
namespace MyProject {
class User { }
}
namespace YourProject {
class User { }
}
namespace { // 全局代码
echo "这是公共代码";
}
<?php
namespace A;
class User {}
namespace B;
class User {} // 混乱,易出错
📌 使用场景:
| 错误 | 正确做法 |
|---|---|
在命名空间外直接写 echo | 放进 namespace { } 或移到外面 |
| 非静态方法当函数调用 | 要 new 对象 或 加 static |
use 写错位置 | 必须在 namespace 后,其他代码前 |
| 文件编码问题 | 推荐 UTF-8,可用 declare(encoding='UTF-8'); |
use 简化长名字根空间 \
├── Admin\User → \Admin\User
├── Student\User → \Student\User
├── MyProject\Order → 当前空间
├── User → 非限定:User → MyProject\Order\User
├── Payment\Pay → 限定:Payment\Pay → MyProject\Order\Payment\Pay
└── \Global\Fun → 完全限定:绝对路径
🔹 命名空间像公司,部门不同名字不撞
🔹 非限定是喊名字,限定是带组名
🔹 完全限定带反斜杠,绝对路径不迷路
🔹use是小名,namespace是指南针
🔹__NAMESPACE__是位置,拼名字它最行
✅ PHP 5.3.0 及以上全部支持命名空间