
如何从零手写一个DI容器基于gh_mirrors/co/container实现PSR-11合规容器的完整教程【免费下载链接】container项目地址: https://gitcode.com/gh_mirrors/co/container本教程基于 gh_mirrors/co/containerPSR-11 标准接口仓库带你从零手写一个 PHP 依赖注入容器DI 容器掌握 PSR-11 合规容器的全部 3 个接口与 2 个核心方法。 为什么值得学DI 容器是现代 PHP 框架如 Laravel、Symfony的基石。读懂 PSR-11 这 3 个几十行的接口文件你就掌握了所有合规容器的公共语言。什么是DI容器1分钟看懂核心思想DI 容器Dependency Injection Container依赖注入容器本质是一个服务工厂传统写法类 A 内部自己new类 B两者强耦合难以测试和替换DI 容器写法把创建对象的职责交给容器类 A 只声明我需要 B由容器统一组装和交付。好处一目了然✅ 依赖集中管理、✅ 便于单元测试可注入 Mock 对象、✅ 替换实现时业务代码零改动。而PSR-11是 PHP-FIG 制定的容器接口标准——它规定任何容器都至少暴露统一的get()和has()方法。gh_mirrors/co/container 正是这份标准的接口定义仓库只有 3 个接口文件、没有一行实现代码这正是我们从零手写的完美起点。PSR-11核心剖析3个接口文件定乾坤仓库结构极其精简src/目录下仅 3 个文件文件作用一句话理解ContainerInterface.php容器主体接口容器的脸面get()has()ContainerExceptionInterface.php容器异常基接口容器出错的统一身份证NotFoundExceptionInterface.php找不到异常接口专门标记查无此服务第一步读懂 ContainerInterface 的两个方法整个 PSR-11 标准的核心就在这两个方法声明里get(string $id)按标识符取对象是容器的主入口has(string $id): bool判断容器是否认识某个标识符。其中有一段非常关键的官方约定src/ContainerInterface.phphas($id)返回 true不保证get($id)一定不抛异常但保证不会抛未找到异常。换句话说has()管有没有这个 keyget()还负责构造这个对象——构造过程中仍可能因其他原因失败。写实现时务必遵守这条语义。第二步理解两级异常体系异常接口只有寥寥数行却设计了清晰的继承链Throwable └── ContainerExceptionInterface容器通用异常 └── NotFoundExceptionInterface未找到异常基接口定义在 ContainerExceptionInterface.php要求所有容器异常都继承它未找到接口定义在 NotFoundExceptionInterface.php专用于key 不存在场景。这样设计的好处调用方可以分级捕获——catch NotFoundExceptionInterface只处理没找到catch ContainerExceptionInterface兜底其他构建失败。错误语义从此清晰可控。3步写出你的PSR-11合规容器一键获取标准接口包标准库通过 Composer 包psr/container分发元数据见 composer.json要求 PHP 7.4命名空间Psr\Container映射到src/目录。获取仓库git clone https://gitcode.com/gh_mirrors/co/container composer require psr/container实现两个方法最简容器诞生手写实现其实非常短——一个数组存服务、两个方法做存取即可?php use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; final class MyContainer implements ContainerInterface { private array $services []; public function set(string $id, $service): void { $this-services[$id] $service; } public function get(string $id) { if (!array_key_exists($id, $this-services)) { throw new class(Service [$id] not found.) extends \RuntimeException implements NotFoundExceptionInterface {}; } return $this-services[$id]; } public function has(string $id): bool { return array_key_exists($id, $this-services); } }对照标准检查一遍get()未找到时抛出的异常实现了 NotFoundExceptionInterface ✅has()返回 bool ✅。两个方法齐全恭喜——你的容器已通过 PSR-11 合规检验注册与获取3行代码感受依赖注入$container new MyContainer(); $container-set(logger, new MonologLogger()); $logger $container-get(logger); // 从容器取而非 new业务类只需声明__construct(Logger $logger)由容器注入实例——依赖倒置就此完成。常见踩坑与最佳实践清单⚠️key 命名要稳定$id是全局契约建议用类型名或语义化名称如logger、app.config⚠️区分没找到和构造失败前者抛NotFoundExceptionInterface后者抛ContainerExceptionInterface的其它实现别混为一谈⚠️has()为 true 不代表get()无异常这是官方明文约定见 src/ContainerInterface.php不要据此省略异常处理✅面向接口编程业务代码依赖ContainerInterface而非你的MyContainer未来无缝切换任何 PSR-11 容器✅进阶方向把set()升级为工厂闭包传入Closure延迟实例化即可实现自动依赖解析这也是各大框架容器的核心机制。总结与延伸资源回顾一下这条从零到合规的路线理解标准——PSR-11 只用 3 个接口定义容器的行为契约实现get()/has()——两行判断、一个数组最简容器即可成立规范异常——用两级异常体系表达没找到与构建失败。 核心资料速查容器主体接口ContainerInterface.php异常基接口ContainerExceptionInterface.php未找到异常接口NotFoundExceptionInterface.php包元数据与自动加载配置composer.json项目说明README.md标准只有薄薄一层真正让 DI 容器变强大的是你的工厂闭包、自动解析和缓存策略。动手把上面的MyContainer扩展成支持工厂的版本吧——你会离手写一个迷你版框架容器只差一小步✨【免费下载链接】container项目地址: https://gitcode.com/gh_mirrors/co/container创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考