configure multiple databases in zf2
If you look at the Zend\Db\Adapter\AdapterServiceFactory, you'll see that your adapter configuration points to only one key 'db'
. Which means that the Adapter that it builds will always use this (unique) configuration key.
I recommend you to create your own factory that would look like this :
namespace Your\Namespace;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Db\Adapter\Adapter;
class MyAdapterFactory implements FactoryInterface
{
protected $configKey;
public function __construct($key)
{
$this->configKey = $key;
}
public function createService(ServiceLocatorInterface $serviceLocator)
{
$config = $serviceLocator->get('Config');
return new Adapter($config[$this->configKey]);
}
}
In your main module (or any other one), add the following to the Module.php file to declare the adapters factories to the Zend Service Manager:
use Your\Namespace\MyAdapterFactory;
use Zend\ModuleManager\Feature\ServiceProviderInterface;
class Module implements ServiceProviderInterface{
//Previous code
public function getServiceConfig()
{
return array(
'factories' => array(
'myadapter1' => new MyAdapterFactory('dbconfigkey1'),
'myadapter2' => new MyAdapterFactory('dbconfigkey2'),
),
);
}
//...
The global config should now look like:
return array(
'dbconfigkey1' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=my_db;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'user',
'password' => '******',
),
'dbconfigkey2' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=my_db2;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
'username' => 'user',
'password' => '******',
),
);
to use the adapters you need to call them using the Service Manager:
$adapter1=$serviceManager->get('myadapter1');
$adapter2=$serviceManager->get('myadapter2');
As of version 2.2
An Abstract Service Factory is now part of the zf2 Zend\Db module. It is possible to add multiples configuration keys under the 'adapters' sub-key :
'db'=> array(
'adapters'=>array(
'adapter' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=test;host=localhost',
'username' => 'readCredential',
'password' => '****'
),
'adapter2' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=test;host=localhost',
'username' => 'rwCredential',
'password' => '****'
),
)
),
However, the AbstractServiceFactory need to be added "manually" as it isn't so by default :
'service_manager' => array(
'abstract_factories' => array(
'Zend\Db\Adapter\AdapterAbstractServiceFactory',
)
),
The adapters are accessible as previously :
$adapter1=$serviceManager->get('adapter');
$adapter2=$serviceManager->get('adapter2');
From a performance perspective this second approach is better : One object will be instantiated (The abstract factory) to (potentially) create the different adapters. Whereas in the previous approach, one object per configuration was created.
Configure multi DB connections on ZF2
Store your connection settings in a local config:
config/autoload/local.php
this is in case you have multiple environments with different databases/connection credentials etc. for example, you may gave a staging setup, and a live setup, both using a separate database.
You can also then use multiple connections inside your application this way too.
there's nothing to stop you setting up multiple connections in here, and using them as needed in your database adapters etc.
local.php
return array(
/**
* Database Connection One
*/
'db' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=dbnamehere;host=localhost',
'username' => 'root',
'password' => '',
),
/**
* Database Connection Two
*/
'db_two' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=anotherdb;host=localhost',
'username' => 'root',
'password' => '',
),
If you are using version control (you should be!) this also allows you to exclude the .local config files from your repository to avoid storing password etc in there, and allows for easier deployment to multiple environments.
You can setup multiple adapters to use different connections too:
global.php
return array(
/**
* Database Adapter(s)
*/
'service_manager' => array(
'factories' => array(
/**
* Adapter One - this factory will use the default 'db' connection
*/
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
/**
* Adapter Two - use the second connection
*/
'Application\Db\AdapterTwo' => function($sm) {
$config = $sm->get('Config');
return new Adapter($config['db_two']);
},
),
),
);
Zend Framework 2 and Doctrine 2 - Configuration for multiple databases
Mac, welcome to stackoverflow! You don't need to define custom factories for each connection respectively. DoctrineORMModule already handles this job for us.
When you need the entity managers, get it from service locator instance by using their names in the alias like this:
$this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
or
$this->getServiceLocator()->get('doctrine.entitymanager.orm_alternative');
I'm sharing one of my current application's database configuration which currently uses both PostgreSQL and MySQL connections.
<?php
return array(
'doctrine' => array(
'connection' => array(
// Default DB connection
'orm_default' => array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver',
'params' => array(
'host' => '1.2.3.4',
'user' => 'pdbuser',
'port' => '5432',
'password' => '****',
'dbname' => 'mydb',
'driver' => 'pdo_pgsql',
),
),
// Alternative DB connection
'orm_alternative' => array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => array(
'host' => '4.5.6.7',
'user' => 'dbuser',
'port' => '3306',
'password' => '****',
'dbname' => 'mydb',
'driver' => 'pdo_mysql',
),
),
),
// Entity Manager instantiation settings
'entitymanager' => array(
'orm_default' => array(
'connection' => 'orm_default',
'configuration' => 'orm_default',
),
'orm_alternative' => array(
'connection' => 'orm_alternative',
'configuration' => 'orm_alternative',
),
),
// Use array cache locally, also auto generate proxies on development environment.
'configuration' => array(
'orm_default' => array(
'metadata_cache' => 'array',
'query_cache' => 'array',
'result_cache' => 'array',
'hydration_cache' => 'array',
'generate_proxies' => true,
),
'orm_alternative' => array(
'metadata_cache' => 'array',
'query_cache' => 'array',
'result_cache' => 'array',
'hydration_cache' => 'array',
'generate_proxies' => true,
),
),
),
);
You can easily merge this configuration with yours.
Hope it helps.
Zend Framework 2 multiple databases
First of all, a better path would be modules/$Module/src/$Module/Db/Adapter/MyAdapterFactory.php
, in conjuction with the namespace $Module\Db\Adapter
(of course not "$Module".. ;) )
The examples of $serviceManager->get('myadapterX')
are merely examples. Anywhere you have access to the ServiceManager you can call these adapter. On the controller level you'd do it this way:
$this->getServiceLocator()->get('myadapterX');
On configuration level when defining a TableGateway or such, it'd probably look something like this:
'my\Table\Gateway' => function ($sm) {
$dbAdapter = $sm->get('myadapterX');
$gateway = new Gateway($dbAdapter);
return $gateway;
}
Related Topics
Loading View Outside View Folder with Codeigniter
Regex Matching Links Without <A> Tag
Display Possible Combinations of String
How to Know If MySQLnd Is the Active Driver
Scaling a Chat App - Short Polling VS. Long Polling (Ajax, PHP)
Having Problems While Try to Install Oauth with Pecl in Mamp on MAC Os Lion
Calculating Distance Between Zip Codes in PHP
Laravel 4 - Logging SQL Queries
PHP Header Location-Redirect Doesn't Work - Why
Using Like in Bindparam for a MySQL Pdo Query
What Is the Use of '\G' Anchor in Regex
Authentication on Google: Oauth2 Keeps Returning 'Invalid_Grant'
How to Destroy the Session Cookie Correctly with PHP
PHP Conditionals, Brackets Needed
How to Get the Unicode Value of a Character or Vise Versa with PHP
What Is the Equivalent of JavaScript's Encodeuricomponent in PHP