PHP-DI 正确安装需用 composer require php-di/php-di,版本≥7.0且PHP≥8.1;接口/抽象类须显式绑定;不可直接替换Laravel/Symfony容器;注解仅开发启用,生产推荐PHP配置。

composer install 时提示 “Package php-di/php-di is not found”
PHP-DI 的官方包名是 php-di/php-di,不是 php-di/container 或带下划线的旧写法。Composer 默认只从 Packagist 拉取公开包,而 PHP-DI 自 6.x 起已完全迁移到该命名空间。
- 运行
composer require php-di/php-di(推荐,自动写入composer.json) - 若手动编辑
composer.json,确保写的是"php-di/php-di": "^7.0"(当前稳定版为 7.x) - 别用
composer install直接装——它只读取现有composer.lock;新包必须用require或update - PHP 版本需 ≥ 8.1(PHP-DI 7 强制要求),
php -v确认,否则会报错Your requirements could not be resolved
PHP-DI 容器初始化后无法解析接口或抽象类
PHP-DI 默认不启用“自动装配”(autowiring)对抽象类型的支持,它只对具体类做构造函数参数自动注入,接口/抽象类必须显式绑定。
- 没绑定就调
$container->get(MyInterface::class)→ 报错No entry or class found for 'MyInterface' - 正确做法:在容器构建时用
addDefinitions()显式映射,例如:$container = \DI\ContainerBuilder::buildDevContainer(); $container->set(\MyApp\LoggerInterface::class, \DI\create(\MyApp\FileLogger::class));
- 也可以用配置文件(
config.php)定义:return [LoggerInterface::class => \DI\create(FileLogger::class)]; - 注意:
set()是运行时绑定,addDefinitions()是构建期加载,后者性能更好、更易测试
在 Laravel 或 Symfony 项目里混用 PHP-DI 导致服务覆盖混乱
主流框架自带容器(Laravel 的 Illuminate\Container\Container,Symfony 的 ServiceContainer),它们和 PHP-DI 不兼容——不能直接把 PHP-DI 实例塞进框架的 app 或 kernel。
- 强行替换框架容器会破坏生命周期钩子(如 Laravel 的
boot()、register()) - PHP-DI 更适合独立脚本、CLI 工具、或作为框架外层封装(比如用 PHP-DI 加载领域服务,再传给框架控制器)
- 若真要集成,只能通过“桥接”方式:让框架容器委托部分接口给 PHP-DI,而不是反向注入
- 常见坑:在
config/app.php里注册ContainerInterface::class到 PHP-DI 实例 → Laravel 启动失败,因核心服务(如Application)依赖原生容器行为
PHP-DI 的注解扫描(@Inject)在生产环境失效
PHP-DI 支持 @Inject 注解,但默认关闭,且生产环境禁用反射扫描——这是性能保护机制,不是 bug。
立即学习“PHP免费学习笔记(深入)”;
- 开发中开启需两步:安装
doctrine/annotations,并在构建容器时加->useAnnotations(true) - 生产环境即使开了,也会跳过注解解析(除非显式设
->enableCompilation()并预生成缓存) - 更稳妥的做法是放弃注解,改用 PHP 配置数组定义依赖,例如:
return [ UserService::class => \DI\create() ->constructor(\DI\get(UserRepository::class)) ]; - 注解带来的隐式依赖会让调试变难,尤其当 IDE 不识别
@Inject时,跳转定义直接失败
Container 实例通常对应整个 CLI 命令或一个长生命周期进程。










