Zend Framework 2 : Using Doctrine Extension with DoctrineModule and DoctrineORMModule
In ZF2, by using DoctrineModule, we can manage the extension that implements
Doctrine\Common\EventSubscriber
in configuration. For example, we have TablePrefix
subcsriber to set table prefix query result like the following :
namespace Application\DoctrineExtension; use Doctrine\ORM\Event\LoadClassMetadataEventArgs; use Doctrine\Common\EventSubscriber; class TablePrefix implements EventSubscriber { protected $prefix = ''; public function __construct($prefix) { $this->prefix = (string) $prefix; } public function getSubscribedEvents() { return ['loadClassMetadata']; } public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs) { $classMetadata = $eventArgs->getClassMetadata(); $classMetadata->setTableName($this->prefix . $classMetadata->getTableName()); foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) { if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY) { $mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name']; $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName; } } } }
Because above class need a dependency at __construct part, we need to build the instance via service manager factory :
use Application\DoctrineExtension\TablePrefix; return [ 'service_manager' => [ 'factories' => [ 'tablePrefix' => function($sm) { // for cache-able config, use factory instead! return new TablePrefix('app.'); }, ], ], //... ];
And now, we can register to the ‘subscribers’ key under ‘orm_default’ ( if we use ‘orm_default’ as connection ).
return [ // ... 'doctrine' => [ // ... common doctrine driver config here 'eventmanager' => [ 'orm_default' => [ 'subscribers' => [ 'tablePrefixService', ], ], ], // ... ], //... ];
And when we call it :
$albumQb = $this->getServiceLocator() ->get('Doctrine\ORM\EntityManager')->getRepository('Application\Entity\Album') ->createQueryBuilder('a'); echo $albumQb->getQuery()->getSql();
It will produce :
SELECT a0_.id AS id0, a0_.artist AS artist1, a0_.title AS title2 FROM app.album a0_
Now… What if the Extension doesn’t extends the Doctrine\Common\EventSubscriber
?
We need to register it in the EventManager of Doctrine Connection as new event listener with utilize DoctrineORMModule, so we have to override the DoctrineORMModule\Service\EntityManagerFactory
:
namespace Application\Factory\Service; use DoctrineORMModule\Service\EntityManagerFactory as BaseEntityManagerFactory; use Doctrine\ORM\EntityManager; use DoctrineModule\Service\AbstractFactory; use Zend\ServiceManager\ServiceLocatorInterface; class EntityManagerFactory extends BaseEntityManagerFactory { /** * {@inheritDoc} * @return EntityManager */ public function createService(ServiceLocatorInterface $sl) { /* @var $options \DoctrineORMModule\Options\EntityManager */ $options = $this->getOptions($sl, 'entitymanager'); $connection = $sl->get($options->getConnection()); $config = $sl->get($options->getConfiguration()); $sl->get($options->getEntityResolver()); // add Table Prefix $evm = $connection->getEventManager(); // assumed 'tablePrefixService' already registered in service_manager before... $evm->addEventListener(\Doctrine\ORM\Events::loadClassMetadata, $sl->get('tablePrefixService')); return EntityManager::create($connection, $config, $evm); } }
Now, we override the ‘doctrine_factories’ config in our config :
return [ 'doctrine' => [ // ... common doctrine driver config here ], 'doctrine_factories' => [ 'entitymanager' => 'Application\Factory\Service\EntityManagerFactory', ], ];
To make it works, The "doctrine_factories"
override config need to be placed after the doctrine
config.
That’s it. I hope it useful ๐
References :
1. http://marco-pivetta.com/doctrine-orm-zf2-tutorial/
2. http://stackoverflow.com/questions/12841102/how-to-configure-doctrine-extensions-in-zend-framework-2
3. https://gist.github.com/samsonasik/90f041f049d509161d61
4. https://github.com/doctrine/DoctrineModule
5. https://github.com/doctrine/DoctrineORMModule
Doctrine entity already mapped to the DB table. Why i need this prefix?
Can you explain with real world practical example?
that.just.a.sample. Anyway, there is a case when you need have separated group of tables, like if you use wordpress with ‘wp_’ prefix, and you need custom business, you have ‘app_’ or ‘product_’ prefix. You can remove on specific case and re-add the tablePrefix eventListener when needed.
… and because I hate re-type ๐
Hi samsonasik, I really don’t now, will be a question within this theme, but… Do you work with a doctrine 2 UniqueObject validation using two fields and if yes, please explaine how..
no, sorry ๐
Hello….
I tested it and it worked ok …
I have to declare in application …
Example:
Portal – Prefix -> user portal
Support- prefix-> suportt_user
Hi samsonasik, i’m trying to use the event listeners to do a little log from the inputs in the DB, but i can’t get it done.. do you have something about it?
i’d tried to do it base on this post but it didn’t work… hope you can help me. thanks