-
-
Notifications
You must be signed in to change notification settings - Fork 455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow service repositories to be used with more than one manager #1044
Comments
I'm -1 for this solution, for several reasons:
IMO, the correct way to support setups with multiple entity managers would be to make sure that we define separate repository factories for each entity manager (I think we might be using the same one right now), and providing a way to register different entity repository services in each of them (which of course won't work with auto-registration of services as it will require multiple instance, but that's fine to me). Also, it would avoid adding extra complexity in repository classes at runtime. |
Hi @stof
To me it's the responsibility of the developer to ensure a proper isolation when using many entity managers so of course many bad things could happen if not done properly, but like with anything else.
$extra won't be autowired but it does not prevent the repository to be currently auto-registered like any others service repositories (else it would be pointless). Let me know if I'm missing something here, but the auto-injection of any services in such repo is not impacted and the repo auto-registers just fine. Anyway, thanks for the feedback, I'll dig into your 3rd point so if you can link to the code you're talking about that would be nice! |
I agree with @stof here. We discourage managing one entity with multiple managers, but are aware that there may be specific use-cases to do so. As I've said previously, service repositories aim to cover 90% of all use-cases, while keeping the entire system flexible enough to allow users to build a solution for their problem. In this case, I don't see how your solution would make it any easier, as you are now essentially just injecting a repository factory into a controller, except that you call it a repository. Please note that we may change the concept of multiple entity managers in the future: it can certainly solve some problems, but it can also cause a lot of problems if abused. Service repositories is one of those features that breaks if the multiple manager concept is abused, and I believe it's best if people figure out a solution for their specific problem rather than us trying to come up with a generic one-size-fits-all type solution. |
Thanks for your comments! Closing the issue till there is more to talk about on the subject! |
Hi,
This is related to symfony/symfony-docs#9878 and may be as an answer to this very informative comment: symfony/symfony-docs#9878 (comment)
Different entity managers can be defined to manage a common set of entities (ref: https://symfony.com/doc/current/doctrine/multiple_entity_managers.html). It is a valid configuration set but this is not well supported by the boilerplate code generated by standard utilities such as
make:entity
or even by the internalManagerRegistry
class (see issue below).However due to doctrine/persistence#68, it is currently not possible to have service repositories that can use an
EntityManager
different than "the first one defined to manage a given entity".Speaking with code, these are the issues encountered with standard boilerplate code:
The issue is:
$a === $b
, when$a should be !== $b
However, when the repository is defined as a non-serviceable repository (the "old way"), this works:
But this legacy definition of a repository does not allow service repositories.
Again, the issue is doctrine/persistence#68 and cannot really be solved because there is no way to know what entity manager should be used at autowiring when multiple entity managers can manage a given entity. The first defined takes it all.
As a solution to this issue I'd like to propose the following approach:
Example:
This way:
1 - Current behavior does not change. It's also backward compatible.
2 - Unexpected behavior is fixed, the correct em is used accordingly (
$d !== $e
).3 - Service repositories can be used in any configuration with no specific limitation to know about first or custom glue code.
How is it implemented?
Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository is rewritten to automatically generate a new (lazy) instance of the entity repository class when a different manager than the default autowired-one is specified by the user with the
withManager
method.On the user side, it requires a minimal change in the constructor of the (service) repository (BC):
This constructor definition allows the new
ServiceEntityRepository
class to create behind-the-scenes new (lazy) instances ofGentlePuppyRepository
but with a specificEntityManager
instance (contained in the$extra
args) and with the very same services instances than initially injected by the user.Implementation details:
And to fix the unexpected current behavior reported above, a fix in Repository\ContainerRepositoryFactory can thus be done as follow:
Any toughts?
The text was updated successfully, but these errors were encountered: