用 PSR-4 命名空间来组织你的代码,并让 Composer 替你加载类和依赖。
在 Kodokon 中打开本课命名空间消除了名称冲突:两个库可以各自定义一个 Client 类而互不冲突。通用的约定:一个供应商前缀(App、Acme\Blog),然后是映射文件夹树的子命名空间。use 把一个完全限定名导入到当前文件,as 则在有歧义时给它改名。一个文件 = 一个类 = 一个命名空间:这条纪律不是什么风格上的怪癖,而是自动加载得以成立的根本前提。
<?php
declare(strict_types=1);
namespace App\Service;
use App\Repository\UserRepository;
use Psr\Log\LoggerInterface as Logger;
final class UserService
{
public function __construct(
private UserRepository $users,
private Logger $logger,
) {
}
}自动加载按需载入类文件:不再需要手动 require。PSR-4 标准定义了这套映射:一个命名空间前缀与一个根文件夹关联,每个子命名空间对应一个子文件夹。于是 App\Service\UserService 就解析为 src/Service/UserService.php。在底层,这一切都依赖 spl_autoload_register - 下面是最简实现,即使你永远不会重写它,也值得理解一下:
<?php
declare(strict_types=1);
spl_autoload_register(function (string $class): void {
$prefix = 'App\\';
$baseDir = __DIR__ . '/src/';
if (!str_starts_with($class, $prefix)) {
return;
}
$relative = substr($class, strlen($prefix));
$path = $baseDir
. str_replace('\\', '/', $relative)
. '.php';
if (is_file($path)) {
require $path;
}
});
echo 'Autoloader registered';Composer 把这一切工业化了:composer.json 声明你的依赖和你的 PSR-4 映射 - 通常是 "autoload": { "psr-4": { "App\\\\": "src/" } } - 然后 composer install 把这些包下载到 vendor/,并生成 vendor/autoload.php,也就是你整个应用唯一的那句 require。一个关键区别:require 用于生产环境需要的包,require-dev 用于工具链(测试、静态分析),通过 --no-dev 从部署中排除。
composer init --name acme/app --no-interaction
composer require monolog/monolog
composer require --dev phpunit/phpunit
composer dump-autoload -oApp\ 前缀指向 src/,类 App\Blog\PostRepository 位于哪里?composer require --dev 是用来做什么的?