September 26, 2011Marek Kalnik4 min read
Symfony2 has been around for quite a while. Personally, I love how much PHP-oriented it is. It feels much closer to the language base than the first version of the framework. It means less of the magic and more of the important decisions in the hands of the development team. But there is no real framework without some magic, which is sometimes really hard to master.
Enough of the introduction, it is time for the technical stuff. First, let us take a look at some user cases:
In all those cases one of the solutions (or a necessity) is to use multiple databases. So let us do some Symfony2 magic!
Lets say we have a simple blog bundle, which we want to adapt to use its own database. The easy part is configuring the connection:
doctrine: dbal: connections: ... blog: driver: %blog.database_driver% host: %blog.database_host% dbname: %blog.database_name% user: %blog.database_user% password: %blog.database_password% charset: UTF8
Next, create a second entity manager:
doctrine: orm: entity_managers: ... blog: connection: blog mappings: MyAwesomeBlogBundle: ~
Well, we can say that your bundle is configured.
It is easy to find in the official documentation that you can simply do
to use your custom entity manager. But I guess you never actually had to do it, being happy with the default one. So this will require some refactoring. The simplest solution is to specify a parameter in your config, let's say:
parameters: my_awesome_blog.entity_manager.name: blog
If you're going to publish your bundle, set it to 'default', in case somebody wouldn't want to use a separate EM, and you should be safe. Now, you need to pass the parameter to each (well, most of) getEntityManager calls in your bundle. It will be a bit of work, depending on the was you used that function. Let's hope you defined some services, like this one:
my_awesome_blog.content_repository: class: %my_awesome_blog.content_repository.class% arguments: ['@doctrine.orm.entity_manager']
or some functions like
in your controllers. Don't worry about the extra work, at least it will help you to decouple your code even more (and we like loosely coupled code, don't we?).
It depends. These are the basics. Things are getting tricky when:
You will need to overwrite the user provider, and pass your custom entity manager to it. In the simplest form it will be something like that:
# security.yml security: providers: blog_user: id: my_awesome_blog.user_provider #this is the name of your service
Now you need to register a simple service which will use your custom entityManager:
# services.yml parameters: my_awesome_blog.user_provider.class: Symfony\Bridge\Doctrine\Security\User\EntityUserProvider my_awesome_blog.user_provider.user.class: MyCompany\MyAwesomeBlogBundle\Entity\User my_awesome_blog.user_provider.user.parameter: username
services: my_awesome_blog.user_provider: class: %my_awesome_blog.user_provider.class% arguments: - '@doctrine.orm.blog_entity_manager' - %my_awesome_blog.user_provider.user.class% - %my_awesome_blog.user_provider.user.parameter%
This one will allow you to use a standard "form_login" configuration, as long as you pass the provider to your firewall (see security reference if you're not familiar with the config options: http://symfony.com/doc/2.0/reference/configuration/security.html).
This one is a little tricky. By default most of internal functions use
Well, if you ever find anything else, and you don't feel like defining your very own service, just try to use the awesome getEntityManagerForClass() function and overload some default classes.
Defining your own entity manager seems easy. This part of Symfony2 configuration is awesome. It is easy, as long as you're not trying to force it to do some more complicated stuff. After a certain point, you find a bunch of default services, which you need to redefine/overload/give up on using at all. Well, whether you really need to do this, or just want to see how it would be like... I wish you best of luck, and don't forget to share your experience!
Web Developer at Theodo