DDC-517: Allow EntityManager configuration to be updated. #644

Closed
opened 2026-01-22 12:45:28 +01:00 by admin · 7 comments
Owner

Originally created by @doctrinebot on GitHub (Apr 13, 2010).

Jira issue originally created by user drak:

This is relating to the Doctrine\ORM\EntityManager and configuration. I would like to suggest adding the ability to add additional MetadataDriver paths, ProxyDirs and ProxyNamespaces to an existing EntityManager.

From what I understand, the EntityManager is configured once to manage all entities for an application.  I may be missing something obvious, but I came across a limitation.  The EntityManager has been designed to cope with a single application only.

In my instance I am writing a system that will host multiple modules that will work together depending on the request.  Modules are supposed to be self contained meaning all Entities/Proxies would be contained in the module's own folder. Modules also can expose APIs to other modules.

controller.php
/module/Foo/...
/module/Bar/...
/module/Beer/...

The controller requests Foo.  In this case it is easy to setup the EntityManager for Foo then pass control to Foo.  But if Foo calls an API from module Bar then the EntityManager has already been configured and it is not possible to add Bar to the EntityManager because it has already been configured and cannot be updated.  

Also, since the last refactor, we can pass an array to $config->newDefaultAnnotationDriver, but we can't pass multiple values to setProxyDir and setProxyNamespace so we are again bound to having all proxies in one place.

So in summary, I would like to suggest

  1. Adding the ability to have multiple proxyDirs/namespaces in the configuration class.
  2. Adding the ability to add additional MetadataDriver paths, ProxyDirs and ProxyNamespaces to an existing EntityManager to allow Doctrine to handle encapsulated modules.
Originally created by @doctrinebot on GitHub (Apr 13, 2010). Jira issue originally created by user drak: This is relating to the Doctrine\ORM\EntityManager and configuration. I would like to suggest adding the ability to add additional MetadataDriver paths, ProxyDirs and ProxyNamespaces to an existing EntityManager. From what I understand, the EntityManager is configured once to manage all entities for an application.  I may be missing something obvious, but I came across a limitation.  The EntityManager has been designed to cope with a single application only. In my instance I am writing a system that will host multiple modules that will work together depending on the request.  Modules are supposed to be self contained meaning all Entities/Proxies would be contained in the module's own folder. Modules also can expose APIs to other modules. controller.php /module/Foo/... /module/Bar/... /module/Beer/... The controller requests Foo.  In this case it is easy to setup the EntityManager for Foo then pass control to Foo.  But if Foo calls an API from module Bar then the EntityManager has already been configured and it is not possible to add Bar to the EntityManager because it has already been configured and cannot be updated.   Also, since the last refactor, we can pass an array to $config->newDefaultAnnotationDriver, but we can't pass multiple values to setProxyDir and setProxyNamespace so we are again bound to having all proxies in one place. So in summary, I would like to suggest 1. Adding the ability to have multiple proxyDirs/namespaces in the configuration class. 2. Adding the ability to add additional MetadataDriver paths, ProxyDirs and ProxyNamespaces to an existing EntityManager to allow Doctrine to handle encapsulated modules.
admin added the Improvement label 2026-01-22 12:45:28 +01:00
admin closed this issue 2026-01-22 12:45:28 +01:00
Author
Owner

@doctrinebot commented on GitHub (Apr 13, 2010):

Comment created by romanb:

  1. Why must the proxies be separated? The proxies of all modules can happily live together in a common directory. I mean, the proxies are not really part of the codebase of the modules, they are more like generated helper classes for the runtime.

  2. Have a look at Doctrine\ORM\Mapping\Driver\DriverChain. Different parts of your application can use different metadata drivers. I.e. "module 1" could use annotations, "module 2" xml and "module 3" yaml.

@doctrinebot commented on GitHub (Apr 13, 2010): Comment created by romanb: 1) Why must the proxies be separated? The proxies of all modules can happily live together in a common directory. I mean, the proxies are not really part of the codebase of the modules, they are more like generated helper classes for the runtime. 2) Have a look at Doctrine\ORM\Mapping\Driver\DriverChain. Different parts of your application can use different metadata drivers. I.e. "module 1" could use annotations, "module 2" xml and "module 3" yaml.
Author
Owner

@doctrinebot commented on GitHub (Apr 13, 2010):

Comment created by romanb:

See: http://www.doctrine-project.org/documentation/manual/2_0/en/configuration:multiple-metadata-sources

@doctrinebot commented on GitHub (Apr 13, 2010): Comment created by romanb: See: http://www.doctrine-project.org/documentation/manual/2_0/en/configuration:multiple-metadata-sources
Author
Owner

@doctrinebot commented on GitHub (Apr 13, 2010):

Comment created by drak:

Thank you for your response.

  1. I see, so proxies can just be in a general folder, a bit like a common cache folder and assigned a single unique namespace.
    Out of interest, is there handling to make sure that there will never be a clash of generated proxy classes?. e.g. if module1 has an Entity called Module1\Entities\Comments and module2 had Module2\Entities\Comments, would My\Proxies generate My\Proxies\Comments for both (i.e. clash) or somehow would the namespace be included so that two separate Proxies could be generated like My\Proxies\Module1_Entities_Comments and My\Proxies\Module2_Entities_Comments? Just thinking out loud.

  2. Maybe I'm just not clear to be how I would add a DriverChain to the EntityManager so forgive my detailed reply: but I am not sure this solves the problem as the issue is the ability to add more namespaces to the metadata drivers after the EntityManager has been created. This is not one application, but a framework that runs multiple modules together and it's not possible to know what parts because that may very well be determined persistent data also (like module x hooks to module y on action z).

e.g. on startup

$driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/Module1/Entities');
$em = EntityManager::create(...)

at some point in Module1, we invoke Module2's API so we need to be able to somehow (pseudo-code)
$em->addDriver($annotations, '/path/to/lib/Module2/Entities');

Now according to the database, a hooks table says that when Module1 creates something, it should run Module3's API to say hook comments on. So again we need to tell the EntityManager about Module3. In this case the fact that Module3 was invoked at all could not have been predicted because it was a hook stored in the DB. This is why we need the ability to register new namespaces as we need them. This sort of use is not uncommon, there are many CMS style frameworks which have self-contained modular components which have API and hook actions configured in the database, so I was thinking of this ability not just for myself, but for the likely requirements of any of these environments.

@doctrinebot commented on GitHub (Apr 13, 2010): Comment created by drak: Thank you for your response. 1) I see, so proxies can just be in a general folder, a bit like a common cache folder and assigned a single unique namespace. Out of interest, is there handling to make sure that there will never be a clash of generated proxy classes?. e.g. if module1 has an Entity called Module1\Entities\Comments and module2 had Module2\Entities\Comments, would My\Proxies generate My\Proxies\Comments for both (i.e. clash) or somehow would the namespace be included so that two separate Proxies could be generated like My\Proxies\Module1_Entities_Comments and My\Proxies\Module2_Entities_Comments? Just thinking out loud. 2) Maybe I'm just not clear to be how I would add a DriverChain to the EntityManager so forgive my detailed reply: but I am not sure this solves the problem as the issue is the ability to add more namespaces to the metadata drivers after the EntityManager has been created. This is not one application, but a framework that runs multiple modules together and it's not possible to know what parts because that may very well be determined persistent data also (like module x hooks to module y on action z). e.g. on startup $driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/Module1/Entities'); $em = EntityManager::create(...) at some point in Module1, we invoke Module2's API so we need to be able to somehow (pseudo-code) $em->addDriver($annotations, '/path/to/lib/Module2/Entities'); Now according to the database, a hooks table says that when Module1 creates something, it should run Module3's API to say hook comments on. So again we need to tell the EntityManager about Module3. In this case the fact that Module3 was invoked at all could not have been predicted because it was a hook stored in the DB. This is why we need the ability to register new namespaces as we need them. This sort of use is not uncommon, there are many CMS style frameworks which have self-contained modular components which have API and hook actions configured in the database, so I was thinking of this ability not just for myself, but for the likely requirements of any of these environments.
Author
Owner

@doctrinebot commented on GitHub (Apr 13, 2010):

Comment created by @beberlei:

There is:

$em->getConfiguration()->getMetadataDriverImpl()->addPaths()

@doctrinebot commented on GitHub (Apr 13, 2010): Comment created by @beberlei: There is: ``` $em->getConfiguration()->getMetadataDriverImpl()->addPaths()``` ```
Author
Owner

@doctrinebot commented on GitHub (Apr 13, 2010):

Comment created by romanb:

@1) Exactly. They wont clash. The name of the proxy class is created based on the full concatenated namespace of the original class. So if you have entities Module1\Entities\Comment and Module2\Entities\Comment the proxy classes would be: My\Proxies\Module1EntitiesCommentProxy and My\Proxies\Module2EntitiesCommentProxy. There are no clashes.

@2) A DriverChain *is* a Driver (composite pattern). Hence you do:

$driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/Module1/Entities');
$driverChain = new DriverChain;
$driverChain->addDriver($driverImpl, 'Module1/Entities');
// the chain is our driver
$config->setMetadataDriverImpl($driverChain);
// finally...
$em = EntityManager::create(...)

The Symfony 2 Doctrine 2 Bundle works exactly like this. Each bundle ("module") can have its own entities and for each bundle a metadata driver is registered in the chain. Of course you can register the drivers on the chain dynamically during runtime. I think nothing prevents you from doing anywhere in your program:

$moduleXMetadataDriver = ...
$config->getMetadataDriverImpl()->addDriver($moduleXMetadataDriver, 'ModuleX\Entities')
@doctrinebot commented on GitHub (Apr 13, 2010): Comment created by romanb: @1) Exactly. They wont clash. The name of the proxy class is created based on the full concatenated namespace of the original class. So if you have entities Module1\Entities\Comment and Module2\Entities\Comment the proxy classes would be: My\Proxies\Module1EntitiesCommentProxy and My\Proxies\Module2EntitiesCommentProxy. There are no clashes. @2) A DriverChain **is\* a *Driver** (composite pattern). Hence you do: ``` $driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/Module1/Entities'); $driverChain = new DriverChain; $driverChain->addDriver($driverImpl, 'Module1/Entities'); // the chain is our driver $config->setMetadataDriverImpl($driverChain); // finally... $em = EntityManager::create(...) ``` The Symfony 2 Doctrine 2 Bundle works exactly like this. Each bundle ("module") can have its own entities and for each bundle a metadata driver is registered in the chain. Of course you can register the drivers on the chain dynamically during runtime. I think nothing prevents you from doing anywhere in your program: ``` $moduleXMetadataDriver = ... $config->getMetadataDriverImpl()->addDriver($moduleXMetadataDriver, 'ModuleX\Entities') ```
Author
Owner

@doctrinebot commented on GitHub (Apr 13, 2010):

Comment created by drak:

Thank you very much for your answers. Might be nice to add this to the Doctrine 2 documentation.

@doctrinebot commented on GitHub (Apr 13, 2010): Comment created by drak: Thank you very much for your answers. Might be nice to add this to the Doctrine 2 documentation.
Author
Owner

@doctrinebot commented on GitHub (Apr 13, 2010):

Issue was closed with resolution "Fixed"

@doctrinebot commented on GitHub (Apr 13, 2010): Issue was closed with resolution "Fixed"
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#644