Symfony服务析构函数多次调用

时间:2018-06-25 19:08:18

标签: php symfony service destructor symfony4

我已经使用Symfony 4一段时间了,最​​近我为我的一个网页创建了一个树枝扩展名,该扩展名负责根据数据库中的数据转换任何给定的字符串。不幸的是,我遇到了一个无法解决的怪异问题。我会尝试按时间顺序记录发生的事情,因此更容易理解。

  1. DatabaseTranslateExtension在Twig中注册了一个新的|translate过滤器。
  2. |translate过滤器触发要构造的惰性加载 TranslationService(当然,还没有构造时)。
  3. 仅创建了一个TranslationService实例(这是预期的)。
  4. 构造函数会预加载数据,因此不会在每次转换时都调用数据库。
  5. 过滤器调用translate方法,该方法转换字符串或(如果数据库中没有翻译)将字符串添加到实例变量中,我们将其称为stringsToTranslate,这是一种数组(String[])。
  6. 翻译完所有字符串后,应调用该服务的析构函数,这会将stringsToTranslate数组刷新到数据库中。

我最近意识到数据库中有很多重复项,因此我尝试调试该应用程序并查看发生了什么。不知何故,我什至不知道它是不可能的,该服务的析构函数被调用两次,而不是一次。我很确定Symfony与它有关(可能是由于延迟加载)或它创建的一些反映类。我想知道是否有什么可以想到的,它将触发析构函数被调用两次(是的,它是类的完全相同的实例)。预先谢谢你。


我确实在一个内置的应用程序中跟踪了代码,并找到了为我的服务创建的包装器,该包装器称为析构函数,这是代码:

public function __destruct()
{
    $this->initializer2b670 || $this->valueHolder90d49->__destruct();
}

有趣的是,此__destruct也被两次调用。似乎是因为还创建了Reflection类,并且两个类都调用destruct。 我确实抛弃了__destructor的尸体。第一个评估是false,这意味着它需要在valueHolder类上调用一个析构函数,然后再次调用对true求值的对象(可能也调用了destruct)。很奇怪。

1 个答案:

答案 0 :(得分:1)

万一遇到类似的问题,请使用KernelEvents::RESPONSEKernelEvents::TERMINATE代替__destructor

  • KernelEvent::RESPONSE在发送响应之前被触发。
  • 发送回复后会触发
  • KernelEvent::TERMINATE

有关here的Symfony生命周期/事件的更多信息。


对于那些对__destruct感到好奇的人,可能是因为在包装器顶部创建了反射类。普通的类实例和反映的类实例被破坏了,我可能会这样称呼它几次。