On demand doctrine database switch with Zend 3

When working on different database with Zend, you may load defined parameters from your local configuration files depending on the action you need to trigger.

In the case you need to load a database which is defined by a specific environment for instance from a session data, you need to update your configuration inside your zend scripts.

To give you an illustration, imagine you have a database with a user table where the database name depends on a user entry :

CREATE TABLE user (
   id BIGINT UNSIGNED NOT NULL PRIMARY KEY,
   ...
   database_name VARCHAR(150),
   ...
) /*..*/

Note the doctrine.connection.orm_example parameter which is taken from our project local.php configuration file as follow :

    'connection' => [
            'orm_default' => [
                    'driverClass' => PDOMySqlDriver::class,
                    'params' => [
                            'host'     => '127.0.0.1',
                            'user'     => 'test',
                            'password' => 'mypassword',
                            'dbname'   => 'test',
                    ]
            ],
            // adding other database for applications
            'orm_example' => [
                    'driverClass' => PDOMySqlDriver::class,
                    'params' => [
                            'host'     => '127.0.0.1',
                            'user'     => 'test',
                            'password' => 'mypassword',
                            'dbname'   => '###'
                    ]
            ],
    ],
    'entitymanager' => [
        'orm_example' => [
                'connection' => 'orm_example',
        ]

The database name which is set here during the configuration phase is not important as we will overwrite this element on Application loading.

Application configuration

This is an essential part of the project as we are updating the database name depending on a session parameter.

The session container will be instantiated during Application loading so it can be handled by any module. In the case the session data of interest is not set, nothing will happen, the module which needs the database won’t be able to load it (proper error handling will be important).

The initial configuration data containing the database name will be updated before any module loading, that ‘s the reason of the presence of the implementation during application initialisation.

Zend configuration process

Before we go any further, let’s have a short reminder of the configuration process sequence in a Zend application. You may read additional information from Zend administration tricks.

Configuration sequence - Zend 3

From the above illustration, you admit that it is not meant to update the configuration data directly from the config array once the service manager is taking the lead. You should act at the 4th step right before any service loading using the EVENT_MERGE_CONFIG event.

The session parameter

One more thing to take care of is the session container which is storing the name of the database which will be used.

For more information on sessions, you can read the tutorial we’ve written here : session data and authentication system in Zend 3. Here we use a container which is defined in the main application as follow :

	'session_containers' => [
			'MyExampleContainer'
	],

We won’t cover the use of sessions here and we need you to assume that the new database name is contained into :

$sessionContainer->dbname = ‘databasename’;

Application initialisation

The different configuration steps occur here in the Module.php of our Application folder. Besides other functions we will add an event which will trigger another function right before the service manager (4th step).

<?php namespace Application; use Zend\ModuleManager\Feature\ConfigProviderInterface; use Zend\Mvc\Controller\AbstractActionController; use Zend\Mvc\MvcEvent; use Zend\ModuleManager\ModuleEvent; use Zend\ModuleManager\ModuleManager; use Zend\Session\Container; class Module implements ConfigProviderInterface { public function init(ModuleManager $moduleManager) { $events = $moduleManager->getEventManager();
		
		// Registering a listener at default priority, 1, which will trigger
		// after the ConfigListener merges config.
		$events->attach(ModuleEvent::EVENT_MERGE_CONFIG, array($this, 'onMergeConfig'));
	}
	
	
	public function getConfig()
	{
		return include __DIR__ . '/../config/module.config.php';
	}
	
	
	/* Update the config with session data for exercice */
	public function onMergeConfig(ModuleEvent $e)
	{
		$configListener = $e->getConfigListener();
		$config         = $configListener->getMergedConfig(false);
		
		$sessionContainer= new Container('MyExampleContainer');
		$dbname = $sessionContainer->dbname;
				
		$config['doctrine']['connection']['orm_example']['params']['dbname'] = $dbname;
		
		
		// Pass the changed configuration back to the listener:
		$configListener->setMergedConfig($config);
	}
}

Note the different import here, our function onMergeConfig() takes a module event as a parameter and the init method needs a module manager to be working.

Then we pass the right database name from our session to the configuration array using the following :

$config[‘doctrine’][‘connection’][‘orm_example’][‘params’][‘dbname’]

Depending on your orm, you may need to update yours.

Well, we are done ! That was easy !

If you have any questions or suggestions, hit me.

Leave a Reply

Want more information?

Related links will be displayed here in this section for you to pick up another good spot to get more details about Web marketing and Search Engine Optimization. There will be some sites which we selected to ease the work of any webmaster or/and web marketer on the Internet.

%d bloggers like this: