Zend_Application: Multiple DB Loading
zend_application_resource, zend_application, zend framework
With addition of Zend_Application in Zend Framework version 1.8, Zend is providing us with a number of classes to make building application easier. In the past I had several classes responsible for setting up my application, initializing database, setting the config, etc...
(NOTE: from ZF 1.10 onwards a MultiDb resource is available in the library: Zend_Application_Resource_Multidb)
It worked fine, but with the new classes looming on the horizon, I decided to try it out.
I managed to setup an application quite quickly. Although I encountered a few bugs, there were no major blocking issues. As a DBA, I often use different databases from a single application. So I need to be able to initiate them in a simple and easy way.
With the Zend_Application, came code for a database resource as well. You basically put your database config in your ini file and bootstrap the database resource. It works like a charm, until you need multiple databases. You can go ahead and extend the database resource for every database you own, but that just doesn't cut it for me. I want a system where I put different databases in my config, and the resource handler takes care of it.
So, I decided to write my first application resource to take care of this. I played around a bit with names and had Multidb at first, but settled for dbs in the end (short for databases).
I had to add following lines to my config file:
# Add my class namespace for the autoloader autoloadernamespaces.amz = "Amz_" # Add my resource path to the plugin path pluginpaths.Amz_Application_Resource = "Amz/Application/Resource" # DB 1 resources.dbs.db1.adapter = PDO_MYSQL resources.dbs.db1.params.dbname = db1 resources.dbs.db1.params.username = user1 resources.dbs.db1.params.password = ****** resources.dbs.db1.params.hostname = localhost resources.dbs.db1.isDefaultTableAdapter = false # DB 2 resources.dbs.db2.adapter = PDO_MYSQL resources.dbs.db2.params.dbname = db2 resources.dbs.db2.params.username = user2 resources.dbs.db2.params.password = ****** resources.dbs.db2.params.hostname = localhost resources.dbs.db2.isDefaultTableAdapter = false
My new resource class looks like this:
<?php
/**
* Amazium Library
*
* @category Amz
* @package Amz_Application
* @subpackage Resource
* @copyright Copyright (c) 2009 Amazium (http://www.amazium.be)
*/
/**
* Resource for creating multiple database adapters
*
* @uses Zend_Application_Resource_Base
* @category Amz
* @package Amz_Application
* @subpackage Resource
* @copyright Copyright (c) 2009 Amazium (http://www.amazium.be)
*/
class Amz_Application_Resource_Dbs extends Zend_Application_Resource_ResourceAbstract
{
/**
* Adapter to use
*
* @var array
*/
protected $_db = array();
/**
* Default adapter
*
* @var boolean
*/
protected $_defaultDb = null;
/**
* Adapter type to use
*
* @return string
*/
public function getAdapter($db)
{
$db = $this->isValidDb($db);
if (isset($this->_options[$db]['adapter'])) {
return $this->_options[$db]['adapter'];
}
return null;
}
/**
* Adapter parameters
*
* @return array
*/
public function getParams($db)
{
$db = $this->isValidDb($db);
if (isset($this->_options[$db]['params'])) {
return $this->_options[$db]['params'];
}
return array();
}
/**
* Is this adapter the default table adapter?
*
* @return void
*/
public function isDefaultTableAdapter($db)
{
$db = $this->isValidDb($db);
if (isset($this->_options[$db]['isDefaultTableAdapter'])) {
return $this->_options[$db]['isDefaultTableAdapter'];
}
return false;
}
/**
* Retrieve initialized DB connection
*
* @return null|Zend_Db_Adapter_Interface
*/
public function getDbAdapter($db = null)
{
// check if the DB is valid
$db = $this->isValidDb($db, true);
if (is_null($db) && is_null($db = $this->_defaultDb)) {
return null;
}
if ((!isset($this->_db[$db]) || (null === $this->_db[$db]))
&& (null !== ($adapter = $this->getAdapter($db)))
) {
$this->_db[$db] = Zend_Db::factory($adapter, $this->getParams($db));
}
return $this->_db[$db];
}
/**
* Defined by Zend_Application_Resource_IResource
*
* @return void
*/
public function init()
{
if (is_null($this->_defaultDb)) {
$options = $this->getOptions();
$defaultDb = null;
foreach ($options as $db=>$dbOptions) {
if (null !== ($adapter = $this->getDbAdapter($db))) {
if ($this->isDefaultTableAdapter($db) || is_null($defaultDb)) {
$defaultDb = $db;
}
}
}
if (!is_null($defaultDb)) {
$this->_defaultDb = $defaultDb;
Zend_Db_Table::setDefaultAdapter($this->getDbAdapter($defaultDb));
}
}
}
/**
* Check if a database key is valid
*
* @param string $db
* @param boolean $revertToDefaultDb
* @return string
*/
public function isValidDb($db, $revertToDefaultDb = false)
{
$db = strtolower(trim($db));
if (!in_array($db, array_keys($this->_options))) {
if (!$revertToDefaultDb) {
$db = $this->_defaultDb;
} else {
throw new Zend_Application_Resource_Exception('Invalid database specified');
}
}
return $db;
}
}
And last but not least, here's my Bootstrap file for loading and using the database:
class Bootstrap extends Zend_Application_Bootstrap_Base
{
public function run()
{
$this->bootstrap('dbs');
$dbs = $this->getPluginResource('dbs');
Zend_Registry::set('db1', $dbs->getDbAdapter('db1'));
Zend_Registry::set('db2', $dbs->getDbAdapter('db2'));
$this->bootstrap('frontController');
$this->frontController->dispatch();
}
}
Enjoy!






+32 475 62.42.64
Shaan
2009-07-13 17:57