多次调用 Symfony 服务析构函数

Symfony service destructor called multiple times

我已经使用 Symfony 4 一段时间了,最​​近我为我的一个网页创建了一个 twig 扩展,它负责根据数据库中的数据翻译任何给定的字符串。不幸的是,我遇到了一个我无法解决的奇怪问题。我会尝试按时间顺序写下发生的事情,这样更容易理解。

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

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


我确实在一个构建的应用程序中找到了代码,并找到了为我的服务创建的包装器,它调用了一个破坏,这是代码:

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

有意思的是这个__destruct也被调用了两次。似乎是因为还创建了 Reflection class 并且 classes 都调用了 destruct。 我确实抛弃了 __destructor 的尸体。第一次评估是 false,这意味着它需要在 valueHolder class 上调用 destruct 然后再次调用它评估为 true(可能也称为 destruct ).奇怪。

如果有人遇到类似问题,请使用 KernelEvents::RESPONSEKernelEvents::TERMINATE 而不是 __destructor

  • KernelEvent::RESPONSE 在发送响应之前触发。
  • KernelEvent::TERMINATE 发送响应后触发。

有关 Symfony 的 lifecycle/events 的更多信息,请参见 here


对于多次调用 __destruct 感到好奇的人,这可能是因为在包装器之上创建的反射 class。正常的 class 实例和反射的 class 实例被破坏了我可能会调用它几次。

旧线程,但最近遇到了同样的问题,因此提供反馈以防其他人遇到类似问题。

在我的例子中,它在 Command 中调用 __destruct

我最终 __destruct 被调用了 6 次。我遵循了反射被破坏等的想法。但这与 Symfony 本身有关。

为什么我这么认为?因为它在启动时表现相似 - 它加载所有命令,调用它们的 __construct(尝试将 echo 添加到每个 Command::__construct 然后调用 bin/console about,你会看到所有 echo 都被调用。)

Symfony 为我得到的每个 Command 调用了 __destruct

为了防止这种情况,我不得不在主 AbstractCommand 中调用 execute(我的 class 所有命令都从中扩展),创建了:

protected abstract doExecute():void;

然后我在 AbstractCommand::execute 中调用 doExecute,然后在 execute 的最后我添加了对我在 _destruct 中的逻辑的调用。