EntityRepository's private readonly properties make implementation overly opinionated #7482

Open
opened 2026-01-22 15:52:12 +01:00 by admin · 0 comments
Owner

Originally created by @oojacoboo on GitHub (Mar 5, 2025).

So, the EntityRepository class has all the properties marked as private readonly. The expectation here is that you're going to construct your repository class with these and they'd never need to be changed.

Then comes the repository factory, which returns the repository for use with the EntityManager.

It seems the decision has been made that your repository classes should only be accessed through the EntityManager and that the constructor of your repositories shouldn't be available to pass additional services.

If you attempt to instantiate your repositories with additional services (different per service as would be the logical case), say with a service container - that'll work fine, but you must then use that container within the factory to return your instantiated repositories.

The issue here is that you're now stuck with an EntityManager that's pre-defined for that repository. You cannot pass or update the EntityManager associated with a repository through the factory. If you're using a custom EntityManager, say with a specific connection, and you call $em->getRepository(Foo::class), you'll then end up with the pre-defined EntityManager on that repository, not the EntityManager you're currently calling getRepository with. And, because everything is private readonly on the EntityRepository, you cannot update it either.

Also, the RepositoryFactory::getRepository method is typed to return the EntityRepository and not an interface. So you have to extend the EntityRepository. Otherwise, you could just wrap it and compose your own base class.

Originally created by @oojacoboo on GitHub (Mar 5, 2025). So, the `EntityRepository` class has all the properties marked as `private readonly`. The expectation here is that you're going to construct your repository class with these and they'd never need to be changed. Then comes the repository factory, which returns the repository for use with the `EntityManager`. It seems the decision has been made that your repository classes should only be accessed through the `EntityManager` and that the constructor of your repositories shouldn't be available to pass additional services. If you attempt to instantiate your repositories with additional services (different per service as would be the logical case), say with a service container - that'll work fine, but you must then use that container within the factory to return your instantiated repositories. The issue here is that you're now stuck with an `EntityManager` that's pre-defined for that repository. You cannot pass or update the `EntityManager` associated with a repository through the factory. If you're using a custom `EntityManager`, say with a specific connection, and you call `$em->getRepository(Foo::class)`, you'll then end up with the pre-defined `EntityManager` on that repository, not the EntityManager you're currently calling `getRepository` with. And, because everything is `private readonly` on the `EntityRepository`, you cannot update it either. Also, the `RepositoryFactory::getRepository` method is typed to return the `EntityRepository` and not an interface. So you have to extend the `EntityRepository`. Otherwise, you could just wrap it and compose your own base class.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#7482