I've been playing with Symfony 4 for a while now and I've created a twig extension for one of my webpages recently, which is responsible for translating any given string based on data in database. Unfortunately, I've faced with a weird problem which I cannot resolve. I'll try to write down what happens chronologically, so it's more understandable.
DatabaseTranslateExtension
registers a new |translate
filter in Twig. |translate
filter triggers a lazy-loaded TranslationService
to be constructed (when it's not constructed yet, of course). TranslationService
created (which is expected).translate
method, which either translates the string or (if there's no translation in the database) adds the string into an instance variable, let's call it stringsToTranslate
, which is a type of array (String[]
).stringsToTranslate
array into a database.I recently realized that I have many duplicates in the database, so I tried to debug the app and see what's happening. Somehow, I had no idea it's even possible, the service's destructor is called twice, not once. I'm pretty sure Symfony has something to do with it (it might be because the lazy loading) or some reflect classes it creates. I'm wondering if there's anything you can think of, which would trigger the destructor to be called twice (Yes, it's the exact same instance of a class). Thank you in advance.
I did track the code down in a built app and found the wrapper created for my service, which calls a destruct, here's the code:
public function __destruct()
{
$this->initializer2b670 || $this->valueHolder90d49->__destruct();
}
What's interesting is that this __destruct
is also called twice. It seems like it's because there's also Reflection class created and both classes call destruct.
I did dump the __destructor
's body. First evaluation was false
, which means it needed to call a destruct on the valueHolder
class and then it gets called once again what evaluated to true
(that probably called destruct too). Weird.
In case anyone has a similar problem use KernelEvents::RESPONSE
or KernelEvents::TERMINATE
instead of __destructor
.
KernelEvent::RESPONSE
is fired before response is sent.KernelEvent::TERMINATE
is fired after response is sent.More about Symfony's lifecycle/events can be found here.
For those curious about __destruct
called multiple times, it's probably because of the reflection class created on top of wrapper. The normal class instance and reflected class instance are destructed I probably this calls it a couple of times.