Pimple容器为空,必须手动注册服务或参数才能使用;服务用匿名函数定义并支持依赖注入,参数直接赋值,factory()确保每次返回新实例,protect()用于延迟求值的可变值。
不是“装上就能用”的开箱即用型容器,直接
后调用
报错或返回 null,根本原因在于服务没定义、参数没注入、或工厂行为误用。必须明确区分「服务」和「参数」,并理解匿名函数的执行时机。
为什么 new Container() 后取不到服务?
因为
实例本身是空的——它不自动扫描类、不加载配置、也不预定义任何服务。你必须手动注册服务或参数,否则
会触发
查找失败,最终抛出
或返回
(取决于 PHP 版本和错误报告级别)。
服务必须用匿名函数定义:
参数直接赋值即可:
若想在服务中用到参数,得显式写
,不能靠类型提示自动注入
别把参数当服务用:写成
就变成了单例服务,不是变量
如何让同一个服务每次返回新实例?
默认所有服务都是共享实例(Singleton),即首次
后缓存结果,后续调用复用。如果你需要每次新建对象(比如
、
实例),必须用
包裹匿名函数。
错误写法(总是返回同一个
):
正确写法(每次新建):
只影响该键,不影响其他服务;且不能嵌套使用(比如
无效)
怎么安全地在服务里引用其他服务或参数?
匿名函数签名中的
参数就是当前容器实例,可用来读取其他服务或参数,但要注意循环依赖和执行顺序。
Composer 2.9.6
Composer 2.9.6 是 PHP 生态中高效、稳定的依赖管理工具。此版本在性能与兼容性上进一步优化,改进了依赖解析算法,提升大型项目中的安装与更新速度。它支持并行下载任务,显著减少等待时间,并增强了与私有仓库及镜像源的交互稳定性。同时修复了多项命令行交互与内存使用相关的缺陷,确保在复杂依赖关系下依然可靠运行。无论是新项目初始化还是现有系统维护,Composer 2.9.6 都能为开发者提供流畅、精准的依赖管理体验。
下载
可以安全引用已定义的服务:
参数也支持同方式访问:
禁止循环依赖:A 依赖 B,B 又依赖 A → 运行时报
定义顺序无关,但运行时第一次访问才执行函数,所以只要最终能解析通就行
protect() 是干啥的?什么时候必须用?
当你想把一个**可变值**(比如当前时间、随机数、
)存进容器,又不希望它被当成服务缓存,就得用
。否则 Pimple 会把它当服务处理,首次调用后就固定了。
错误(
只执行一次):
正确(每次取都重新执行):
返回的是闭包本身,不是执行结果;取值时需手动调用:
别对服务用
:它只适用于「你想延迟求值的变量」,不是服务注册机制
Pimple 的核心陷阱不在安装,而在语义混淆:把参数当服务、把服务当变量、忽略
和
的边界。一旦混用,行为就不可预测,调试时很难定位是定义问题还是调用时机问题。
Pimplecomposer require pimple/pimple$container['service']Pimple\Container$container['xxx']ArrayAccess::offsetGetInvalidArgumentExceptionnull$container['db'] = function ($c) { return new PDO(...); };$container['host'] = 'localhost';$c['host']$container['host'] = function () { return 'localhost'; }PimplegetRequestLoggerfactory()Session$container['session'] = function ($c) { return new Session($c['storage']); };$container['session'] = $container->factory(function ($c) { return new Session($c['storage']); });factory()$container->factory($container->factory(...))$c$container['logger'] = function ($c) { return new FileLogger($c['log_path']); };$container['log_path'] = '/var/log/app.log';LogicException: Circular reference detected$_GETprotect()time()$container['now'] = function () { return time(); };$container['now'] = $container->protect(function () { return time(); });protect()$container['now']()protect()factory()protect()