mitchellvanw / laravel-doctrine

NO LONGER MAINTAINED! A Doctrine 2 implementation that melts with Laravel
MIT License
187 stars 74 forks source link

Multiple Entity Managers and Connections #55

Open npmarrin opened 10 years ago

npmarrin commented 10 years ago

This patch provides the ability to reference multiple database connections in laravel-doctrine. It will register the default database or the set of databases outlined in the entity_managers configuration. Existing functionality is maintained by continuing to register the EntityManager and returning a connection from the ManagerRegistry

npmarrin commented 10 years ago

Added a new configuration directive entity_managers that allows for individual configuration of multiple entity managers. This entry will be created automatically if no entity_managers entry is defined

If present each entity manager must be given a name.

An entity manager has the following configuration options:

'entity_managers' => [
    'name' => [              
        // if omitted connection will default to the same name as the entity manager
        'connection' => 'default',  
        // if omitted cache_provider will default to the global cache_provider value
        'cache_provider' => null,
        // if omitted repository will default to the global repository value
        'repository' => 'Doctrine\ORM\EntityRepository',
        // if omitted simple_annotations will default to the global simple_annotations value
        'simple_annotations' => false,
        // if omitted logger will default to the global logger value
        'logger' => null
        // if omitted metadata will default to the global metadata value
        'metadata' => [
            base_path('app/models')
        ],
    ]
]       
glennjacobs commented 9 years ago

Any update on whether this will be merged or not? This looks very handy to me.

kirkbushell commented 9 years ago

If tests can be written to manage all the changes, then we can move forward with the implementation / merge.

glennjacobs commented 9 years ago

:thumbsup:

npmarrin commented 9 years ago

@kirkbushel Do you have a list of tests or features you would like tests added for? Since the old configuration is rebuild into the new format the old test should confirm that basic functionality is still intact.

kirkbushell commented 9 years ago

I do not believe there are any tests for the commands yet - so that would be a good starting point. Would be great to increase our test count and coverage.

npmarrin commented 9 years ago

@kirkbushell Sorry this took so long. I needed to do a little refactoring in order to make it more testable. Let me know your thoughts on this and / or any feedback on any additional tests you need in order to move this forward.

npmarrin commented 9 years ago

Along with the entity_managers a new configuration option default_connection was adding in this pass. This will default to the default database in the laravel database configuration but can be changed when you want to maintain a different list.

From http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html

If you do omit the entity manager's name when asking for it, the default entity manager (i.e. default) is returned

FoxxMD commented 9 years ago

:+1: @npmarrin can you clear up where entity_manager is supposed to live? Does it replace the contents of doctrine.php or live inside it? Also how do I reference what manager to use? Should I be creating a provider for this?

One more thing, this line should be changed to IlluminateRegistry::class

npmarrin commented 9 years ago

@FoxxMD You are correct. Instead of creating an entity manager for the default database we now create a new entry in $app['config']'doctrine::doctrine' called entity_managers. This item will be populated automatically from the default database connection if not specified in $app['config']['database']. This allows a default configuration with the entity name being the same as the database connection. We also create default_connection in $app['config']['doctrine::doctrine'] to match the default in $app['config']['database']. This is important in a multi-connection environment where we may want a doctrine default separate from the listed default in $app['config']['database'].

So the thing to note is if you create an 'entity_managers' entry in doctrine.php it requires its own configuration. Missing items will be filled with some defaults. You then need to set a name for the entity manager and list the matching connection from $app['config']['database'] if they are not the name. Doctrine does not require that the connection and entity name be the same so this provides a little more flexibility. You still need to define the default_connection in doctrine.php outside of the entity_managers array if for some reason this is different from the default connection in $app['config']['database']. If default_connection is not specified then it will be created with from the default value from $app['config']['database'].

If you have any questions/comments I'd be happy to review it.

npmarrin commented 9 years ago

@FoxxMD \Tests\MultipleEntityManagersAndConnections\SchemaCreateCommandTest uses the following connection information. It will call the command with sqlite to use a non-default entity manager for the operation. For reference the test adds the following to doctrine.php.

default_connection = 'mysql',

'entity_managers' = [
    'pgsql' => [
        'connection' => 'pgsql',
        'metadata' => [
            __DIR__.DIRECTORY_SEPARATOR.'Models',
        ],
    ],
    'mysql' => [
        'connection' => 'mysql',
        'metadata' => [
            __DIR__.DIRECTORY_SEPARATOR.'Models',
        ],
    ],
    'sqlite' => [
        'connection' => 'sqlite',
        'metadata' => [
            __DIR__.DIRECTORY_SEPARATOR.'Models',
        ],
    ],
];
``
FoxxMD commented 9 years ago

Thanks @npmarrin ! How do I get a non-default entity manager from code? Right now I'm just using the EntityManager facade provided by laravel-doctrine. Do I need to instantiate a new IlluminateRegistry and do getManager('nonDefaultManager') every time I want one? Or can it be set up using the facade?

npmarrin commented 9 years ago

@FoxxMD You want to replace use Doctrine\ORM\EntityManagerInterface; with use Doctrine\Common\Persistence\ManagerRegistry; and then replace EntityManagerInterface $entityManager with ManagerRegistry $registry. This will inject the IlluminateRegistry. EntityManagerInterface is still available for backwards compatibility.

You can get the default manager using $registry->getManager() or you can pull a specific manager using $registry->getManager('sqlite'). You can also pull a connection from the IlluminateRegistry if you don't need ORM for a specific query. Again their is no requirement that the connection and entity manager names are the same. Only that the connection name is present in database.php. If you are using multiple-connections you should be passing the registry into your controllers.

You can review http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html if you need more background.

If you have any issues / concerns let me know. It is great to get another pair of eyes on this.

FoxxMD commented 9 years ago

Thanks @npmarrin, this has been extremely helpful!