pimple 容器默认为空,必须手动注册服务和参数才能使用;未注册键访问时返回 null 而非抛异常,需用 keys() 或 psr-11 的 get() 捕获异常;单例行为需 factory() 显式声明新实例。

直接运行 composer require pimple/pimple 就能引入,但装完不能直接用——Pimple 容器是空的,所有服务、参数都得手动注册,否则 $container['xxx'] 会报 InvalidArgumentException 或返回 null。
为什么 composer require pimple/pimple 后还是找不到服务?
Pimple 不预定义任何服务,也不扫描类或读配置文件。它就是一个空容器实例,new Pimple\Container() 后你必须显式写:$container['db'] = function ($c) { ... }; 才算注册成功。
- 常见错误:只 new 了容器,没定义任何键,就直接
$container['logger']—— 这不是 bug,是设计如此 - 注意区分「服务」和「参数」:
$container['host'] = 'localhost';是参数;$container['db'] = function ($c) { ... };才是服务 - 参数不能在匿名函数里自动注入,必须显式写
$c['host'],类型提示不起作用 - 如果用了 PSR-11 包装器(
Pimple\Psr11\Container),也要先传入已注册服务的$pimple实例,否则get()一样失败
$container['xxx'] 返回 null 而不是抛异常?
这通常发生在 PHP 错误报告级别未开启 E_WARNING 或 E_NOTICE 时,Pimple 默认用 offsetGet 查找键,未命中会静默返回 null(而非抛出 InvalidArgumentException)。这不是兼容性问题,是行为差异。
- 检查
error_reporting是否包含E_WARNING,或手动加var_dump($container->keys())看当前注册了哪些键 - 别依赖
isset($container['xxx'])判断服务是否存在——Pimple 不实现offsetExists,这个判断永远为false - 想安全取值,用
array_key_exists('xxx', $container->keys())或捕获get()抛出的异常(如果你用了 PSR-11 包装器)
怎么让每次 $container['request'] 都返回新对象?
Pimple 默认所有服务都是单例(共享实例),必须用 factory() 显式包裹匿名函数,否则反复调用得到的是同一个对象。
- 错误写法:
$container['request'] = function ($c) { return new Request(); };→ 总是返回同一实例 - 正确写法:
$container['request'] = $container->factory(function ($c) { return new Request(); }); -
factory()只影响当前键,不影响其他服务;也不能嵌套调用,$container->factory($container->factory(...))无效 - 如果服务依赖参数(如
$c['config']),factory()内照样可访问,执行时机不变
最容易被忽略的一点:Pimple 的「轻量」是双刃剑——它不帮你做自动绑定、不解析注解、不加载 YAML/PHP 配置,所有依赖关系都得手写闭包。你以为配个数组就能跑,其实每行 $container['xxx'] = ... 都是你亲手签下的契约。











