Welcome to Abdul Malik Ikhsan's Blog

Zend Framework 2 : Using Doctrine Extension with DoctrineModule and DoctrineORMModule

Posted in Tutorial PHP, Zend Framework 2 by samsonasik on October 15, 2014

zf2-zendframework2 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' => [
        // ...

And when we call it :

$albumQb = $this->getServiceLocator()
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());

        // 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

6 Responses

Subscribe to comments with RSS.

  1. seyferx said, on October 15, 2014 at 7:46 pm

    Doctrine entity already mapped to the DB table. Why i need this prefix?
    Can you explain with real world practical example?

    • samsonasik said, on October 15, 2014 at 7:59 pm

      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 ๐Ÿ˜›

  2. Andr said, on February 20, 2015 at 2:08 am

    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..

  3. Alecsandro Santos said, on April 30, 2016 at 4:51 am


    I tested it and it worked ok …

    I have to declare in application …
    Portal – Prefix -> user portal
    Support- prefix-> suportt_user

  4. ligiama said, on May 19, 2017 at 12:24 am

    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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: