PHP: 命名空间与自动加载
写小项目时 3 个类够用。但业务代码可能有 300 个类,还要用第三方库——命名空间和 Composer 就是 PHP 生态的"组织系统",让你的代码不会名字撞车。
1. 为什么需要命名空间?
PHP
<?php
// 假设你写了一个 Logger 类
class Logger {
public function log(string $msg): void {
echo "我的日志:{$msg}<br>";
}
}
// 你想用一个第三方包,它也有 Logger 类
// 结果:PHP Fatal Error: Cannot redeclare class Logger
?>
命名空间解决这个问题——相当于给每个类加上"姓氏":
TEXT
📖 仅展示
没有命名空间:Logger ← 撞车!
用了命名空间:MyApp\Logger vs Vendor\Logger ← 不撞!
2. namespace 声明
PHP
<?php
// file: app/Utils/Logger.php
namespace App\Utils;
class Logger {
public function log(string $msg): void {
echo "[LOG] {$msg}<br>";
}
}
// 使用全限定名
$log = new \App\Utils\Logger();
$log->log("程序启动");
?>
命名空间规则:
namespace必须在文件最开头(<?php之后第一行)- 用反斜杠
\分隔层级(和 Windows 用的一样,但含义不同) App\Utils等价于目录App/Utils/
3. use — 导入类
PHP
<?php
namespace App\Controllers;
// use 导入后,直接用类名
use App\Utils\Logger;
use PDO;
use DateTime;
class UserController {
public function index(): void {
$log = new Logger(); // 不需要写全限定名
$log->log("访问用户列表");
$now = new DateTime(); // PHP 内置类,也可以 use
}
}
?>
(1) use ... as — 别名
PHP
<?php
// 解决同名冲突
use App\Models\User as AppUser;
use Vendor\Cms\User as CmsUser;
$u1 = new AppUser();
$u2 = new CmsUser();
?>
4. Composer — PHP 的包管理器
Composer 之于 PHP,就像 npm 之于 Node.js,pip 之于 Python。
(1) 安装 Composer
访问 https://getcomposer.org 下载安装,然后在项目目录:
BASH
# 初始化项目
cd myphp
composer init
# 安装一个包(以常用的 .env 配置库为例)
composer require vlucas/phpdotenv
▶ 示例:composer.json 配置与自动加载
JSON
{
"name": "myphp/demo",
"description": "PHP学习项目",
"require": {
"php": ">=8.0",
"vlucas/phpdotenv": "^5.0"
},
"autoload": {
"psr-4": {
"App\\": "app/"
}
}
}
(2) 使用自动加载
PHP
<?php
// 只需要 require 这一个文件
require __DIR__ . '/vendor/autoload.php';
// 现在可以用 Composer 管理的所有包和自定义类
use App\Models\User;
$user = new User();
?>
5. PSR-4 自动加载
PSR-4 是 PHP 社区的自动加载标准——命名空间前缀对应目录:
| 命名空间 | 对应目录 | 类文件路径 |
|---|---|---|
App\ |
app/ |
app/ 是根 |
App\Models\User |
— | app/Models/User.php |
App\Controllers\Admin\Dashboard |
— | app/Controllers/Admin/Dashboard.php |
▶ 示例:PSR-4 项目结构
TEXT
📖 仅展示
myphp/
├── app/
│ ├── Models/
│ │ └── User.php ← namespace App\Models;
│ └── Controllers/
│ └── UserController.php ← namespace App\Controllers;
├── vendor/ ← Composer 自动创建
│ └── autoload.php
├── composer.json
└── public/
└── index.php
PHP
<?php
// app/Models/User.php
namespace App\Models;
class User {
public function __construct(
public string $name,
public string $email
) {}
}
PHP
<?php
// public/index.php
require __DIR__ . '/../vendor/autoload.php';
use App\Models\User;
$user = new User("小明", "xiaoming@example.com");
echo $user->name; // 小明
?>
6. Composer 常用命令
BASH
# 安装 composer.json 中列出的所有依赖
composer install
# 添加新依赖
composer require guzzlehttp/guzzle
composer require --dev phpunit/phpunit # 仅开发环境
# 更新所有依赖
composer update
# 更新单独某个包
composer update guzzlehttp/guzzle
# 生成优化的自动加载器(生产环境)
composer dump-autoload -o
7. 自带类 vs 命名空间
PHP
<?php
namespace App;
// 在命名空间中调用 PHP 内置类
$date = new \DateTime(); // 根命名空间 \
$pdo = new \PDO($dsn, $user, $pass);
// 或用 use
use DateTime, PDO;
$date = new DateTime();
$pdo = new PDO($dsn, $user, $pass);
?>
💡 提示: 在命名空间内部,PHP 内置类必须加
\ 前缀或 use 导入。不加的话 PHP 会在当前命名空间里找(App\DateTime,根本不存在)。
❓ 常见问题
Q 命名空间一定要和文件路径一样吗?
A PSR-4 规范要求一致,但 PHP 语法上不强制。手动 require 时可以随意命名。但按规范做事,Composer 的自动加载才能工作。
Q Composer 的包安装到哪里了?
A
vendor/ 目录。这个目录通常不提交到 Git(在 .gitignore 中配置)。团队成员用 composer install 自行安装。Q
composer.json 中的 ^5.0 什么意思?A 语义化版本(SemVer)约束。
^5.0 表示接受 >=5.0 且 <6.0 的版本。~5.0 表示 >=5.0 且 <5.1。📖 小节
- 命名空间解决类名冲突:
namespace App\Utils; use导入类,as起别名- Composer 是 PHP 的包管理器(
composer require xxx) - PSR-4:
App\Models\User→app/Models/User.php vendor/autoload.php一行代码让所有类自动加载- 命名空间内用内置类要加
\或use
📝 作业
- 创建一个简单的项目结构:
app/Models/User.php和app/Utils/Validator.php,各自声明命名空间,在public/index.php中用 use 导入并使用。 - 安装 Composer,用
composer init初始化项目,在 composer.json 中配置 PSR-4 自动加载。 - 安装一个第三方包(如
ramsey/uuid用于生成 UUID),理解 vendor 目录和 autoload.php 的作用。