As a Web Developer you will work with many types of hostings and sometimes you have only one database to use. To avoid conflicts with names of tables, you need a different table prefix for each project. By default Symfony doesn’t support such a functionality, but of course it’s easy to implement when needed.
You can use Doctrine Prefix Bundle, but there would be no fun. If you’re not a fan of installing a new bunle for every single functionality, you can write your own TablePrefixSubscriber.
Let’s start
Inside your bundle you have many folders, like Controller, Resources etc. Create a new one and name it Subscriber. Now add a new php file named TablePrefixSubscriber.php and paste the contents bellow. Don’t forget to change the namespace matching your bundle.
<?php namespace Picios\Bundle\LibBundle\Subscriber; use Doctrine\ORM\Event\LoadClassMetadataEventArgs; /** * Description of TablePrefixSubscriber * * @author avanzu */ class TablePrefixSubscriber implements \Doctrine\Common\EventSubscriber { protected $prefix = ''; public function __construct($prefix = '') { $this->prefix = (string) $prefix; } public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) { $classMetadata = $eventArgs->getClassMetadata(); if(strlen($this->prefix)) { if(0 !== strpos($classMetadata->getTableName(), $this->prefix)) { $classMetadata->setTableName($this->prefix . $classMetadata->getTableName()); } } foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) { if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY) { if(!isset($classMetadata->associationMappings[$fieldName]['joinTable'])) { continue; } $mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name']; if(0 !== strpos($mappedTableName, $this->prefix)) { $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName; } } } } public function getSubscribedEvents() { return array('loadClassMetadata'); } }
Next we need to notice Doctrine to use our Subscriber. Find the file Resource/config/services.yml in your bundle directory and add such a declaration in services section.
picios.tblprefix_subscriber: class: Picios\Bundle\LibBundle\Subscriber\TablePrefixSubscriber arguments: [%table_prefix%] tags: - { name: doctrine.event_subscriber }
or xml
<service id="picios.tblprefix_subscriber" class="Picios\Bundle\LibBundle\Subscriber\TablePrefixSubscriber"> <argument>%table_prefix%</argument> <tag name="doctrine.event_subscriber" /> </service>
As you can see, there’s a table_prefix parameter, which hasn’t been defined yet. So let’s go to app/config/parameters.yml and add another parameter:
table_prefix: foo_
We can’t forget to update app/config/parameters.yml.dist with the same parameter to prevent loosing it after a composer action.
As a result, we get a ready to go Doctrine using table prefixes. Now we can easily create many projects within one database. Which is not recommended by the way, but the circumstances sometimes force us to break the programming lows.
Alireza Seddighi says:
Also, you can use this bundle for the new version of Symfony (4) – DoctrinePrefixBundle
Alireza Seddighi says:
https://github.com/borsaco/DoctrinePrefixBundle
Maxim says:
Thak you. Article helped me.
Picios says:
Hi, good to hear that
Stuart Little says:
Is there any way to adapt this for Symfony4 ?
Picios says:
Hi,
In Symfony 4 it’s enough for your class TablePrefixSubscriber to implement \Doctrine\Common\EventSubscriber. The rest is a magic 🙂
Alireza Seddighi says:
Yes it’s https://github.com/borsaco/DoctrinePrefixBundle