应安装psr-11接口的具体实现(如php-di/php-di),而非仅psr/container;后者仅为契约接口,不可实例化,仅用于类型提示与解耦。

直接装 psr/container 没用——它只是接口定义,不提供实现,装了也不能 new ContainerInterface() 出来用。
为什么 composer require psr/container 看似成功却报错?
因为 psr/container 是一个纯接口包(PSR-11),只含 ContainerInterface 和 NotFoundExceptionInterface 等声明,没有具体类。你执行 composer require psr/container 后:
- Composer 确实会下载并写入
vendor/psr/container - 但一旦你写
$container = new \Psr\Container\ContainerInterface();,PHP 会立刻报Fatal error: Cannot instantiate interface - IDE 可能提示“找不到实现类”,类型提示也“悬空”
这不是安装失败,是理解偏差:它不是库,是契约。
真正该装的是实现了 PSR-11 的容器(比如 php-di/php-di 或 symfony/dependency-injection)
要让 DI 容器跑起来,必须选一个具体实现。常见选择和差异:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
-
php-di/php-di:开箱即用,支持注解、自动注入,适合中小型项目;执行composer require php-di/php-di后可直接$container = \DI\ContainerBuilder::buildDevContainer(); -
symfony/dependency-injection:配置驱动、功能全,但需手动写 YAML/PHP 配置;适合已有 Symfony 生态或需要精细控制的场景 -
league/container:轻量、代码优先,API 清晰,适合想自己掌控绑定逻辑的项目
注意:psr/container 通常会被这些实现自动作为 require 声明拉入,无需手动 require —— 手动加反而可能引发版本冲突(如 v1.x vs v2.x 接口微调)。
如何安全地在类型提示中使用 ContainerInterface?
这是 psr/container 的正确打开方式:仅用于解耦和类型约束,不参与实例化。
- 你的服务类构造函数应依赖
Psr\Container\ContainerInterface,而不是某个具体容器类 - 确保
composer.json中已通过实际容器(如php-di/php-di)间接引入psr/container,且版本兼容(推荐"psr/container": "^1.0 || ^2.0") - 如果 IDE 报未解析,检查是否漏了
use Psr\Container\ContainerInterface;,或 Composer autoload 未生效(可试composer dump-autoload)
示例片段:
use Psr\Container\ContainerInterface;
class UserService
{
public function __construct(private ContainerInterface $container) {}
public function getRepo(): UserRepo
{
return $this->container->get(UserRepo::class);
}
}
真正难的不是装哪个包,而是分清「契约」和「实现」——接口包不干活,干活的永远是后面那个你亲手挑的容器实现。漏掉这层,后面所有自动注入、测试替换成都会卡在“类型对不上”或“new 失败”。










