我注意到,只有在调用该服务中的方法时,才会启动Symfony服务(执行构造函数)。如果您的服务只有构造函数而没有方法,那么这很重要。
例如:
class MyService {
public function __construct($someOtherService) {
$someOtherService->setFoo("bar");
}
}
// And of course put this service in services.yml
app.my_service:
class: AppBundle\...\MyService
arguments: [ app.some_other_service ]
在这种情况下,不调用构造函数和setFoo(“bar”)。为什么是这样?是否有可能以某种方式强制服务启动,而无需在此服务上调用(虚拟)方法?
我还尝试为app.my_service添加“lazy:false”,但这没什么区别。
我正在使用Symfony 2.8。
答案 0 :(得分:4)
如果从未使用过您的服务,那么它们永远不会被实例化。要强制实例化服务,您可以挂钩到任何适合您事件的事件侦听器,当您想要获得服务(即kernel.request
)并将此服务作为依赖项传递给侦听器时。这将在容器生命周期内第一次触发事件时触发服务构造函数。
但我建议您查看架构。只使用构造函数服务是无意义的
此外,您可以在EvendDispatcher
实例化时实例化服务(仅因为它取决于您的服务)而不会触发事件
听众样本:
class ServiceInstantiatorListener
{
public function onRequest(KernelEvent $kernel)
{
return; //noop, just make sure it works
}
public function instantiate($service)
{
return $service; // noop again, just call to pass service container argument
}
}
yaml config:
services:
my_app.service_instantiator_listener:
class: My\App\ServiceInstantiatorListener
tags:
- { 'name': 'kernel_events', 'event': 'kernel.request', 'method':'onRequest' }
calls:
- [instantiate, ["@my_app.weird_service_one"]]
- [instantiate, ["@my_app.weird_service_two"]]
更进一步,您可以使用标记标记您的服务,并使用MyAppBundleExtension
编译器通行证动态配置调用
http://symfony.com/doc/current/service_container/tags.html#create-a-compiler-pass
我希望有更好的方法来强制实例化服务(即一些容器内部事件),但目前我还没有遇到我需要的情况。
答案 1 :(得分:1)
您正在描述延迟加载服务的行为。检查lazy: true
的配置并删除/禁用它。
Symfony docs, lazy loaded service:
当您尝试与服务进行交互时,实际的类将被实例化(例如,调用其中一种方法)。
答案 2 :(得分:1)
您并不需要在服务上调用虚拟方法来启动它。 您可以使用以下语句实例化服务对象:
<强> $这 - &GT;容器() - &GT;获得(&#39; app.my_service&#39); 强>