Set the payum.builder service as a non-shared service #551
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The
payum
service is set to use thepayum.builder
as a factory for creating the instance. This means that whenever you inject thePayum
class, it will use thePayumBuilder->getPayum()
method to instantiate the class. ThePayumBuilder
class is also defined as a service in the container, so that all it's dependencies can be added.By default, all services in Symfony are shared, which means you will always get the same instance when requesting a service. Since
PayumBuilder
is used to create all the dependencies forPayum
, and it requires the Twig env which might register an extension that also depends on Payum, it creates a circular dependency. But PayumBuilder is only a factory, and you don't rely on it directly in your classes, so it doesn't cause any errors during compliation.But what does happen, is the order in which the gateway config is added.
Firstly, the
payum.builder
is added to the container, then it loads some dependencies.In this case, the
twig
service is added to the core config before the other config. When the twig service is loaded and an extension is registered that uses thePayum
class, the service container will again use thepayum.builder
factory to create thePayum
instance. But this time thepayum.builder
is already defined in the service container, but doesn't have all the config set yet. So the Payum class will be created, and added to the container (because services are shared by default), which means it won't have all the necessary config added.This PR sets the
payum.builder
as a non-shared service. This means that when creating a Payum instance, it will use the PayumBuilder as a factory, and if PayumBuilder requires a service that relies on Payum, it will create a new instance of PayumBuilder with all the required dependencies. Once a successful instance on Payum is created, it will be added on the container as thepayum
service, which will be re-used whenever thePayum
class is required.This might have a very slight performance penalty, since the
PayumBuilder->getPayum
method might be called multiple times per request (I think it might be at most 2 times), but I think it's acceptable since there are no heavy operation in that method, and it ensures that the Payum service can be injected anywhere without side effects.Fixes #549