Как работать с несколькими БД в ZF? Давайте посмотрим, начнем с конфигурационного файла. Вы ведь используете компонент Zend_Application? Тогда поехали.
Будем придерживаться правильного подхода в разработке приложений. Давайте создадим такой ini файл с настройками для Zend_Application. В конфиге будет одна общая секция, и 3 секции для разных сред выполнения нашего приложения - development, test и production. В каждой из этих секций мы сможем работать с несколькими БД одновременно.
Смотрим конфиг:
; Общие настройки
[bootstrap]
; Подключение к БД #1
resources.dbs.db1.adapter = "pdo_mysql"
resources.dbs.db1.params.host = "localhost"
resources.dbs.db1.isDefaultTableAdapter = true
resources.dbs.db1.params.driver_options.1002 = "SET NAMES utf8"
resources.dbs.db1.params.profiler.enabled = true
resources.dbs.db1.params.profiler.class = Zend_Db_Profiler_Firebug
; Подключение к БД #2
resources.dbs.db2.adapter = "pdo_mysql"
resources.dbs.db2.params.host = "localhost"
resources.dbs.db2.isDefaultTableAdapter = false
resources.dbs.db2.params.driver_options.1002 = "SET NAMES utf8"
resources.dbs.db2.params.profiler.enabled = true
resources.dbs.db2.params.profiler.class = Zend_Db_Profiler_Firebug
; Настройки проекта в стадии development
[development : bootstrap]
; Подключение к БД #1
resources.dbs.db1.params.dbname = "mydatabase_development"
resources.dbs.db1.params.username = "root"
resources.dbs.db1.params.password = ""
; Подключение к БД #2
resources.dbs.db2.params.dbname = "mydatabase2_development"
resources.dbs.db2.params.username = "root"
resources.dbs.db2.params.password = ""
; Настройки проекта в стадии test
[test : bootstrap]
; Подключение к БД #1
resources.dbs.db1.params.dbname = "mydatabase_test"
resources.dbs.db1.params.username = "root"
resources.dbs.db1.params.password = ""
; Подключение к БД #2
resources.dbs.db2.params.dbname = "mydatabase2_test"
resources.dbs.db2.params.username = "root"
resources.dbs.db2.params.password = ""
; Настройки проекта в стадии production
[production : bootstrap]
; Подключение к БД #1
resources.dbs.db1.params.dbname = "mydatabase_production"
resources.dbs.db1.params.username = "root"
resources.dbs.db1.params.password = ""
; Подключение к БД #2
resources.dbs.db2.params.dbname = "mydatabase2_production"
resources.dbs.db2.params.username = "root"
resources.dbs.db2.params.password = ""
В общей секции (bootstrap) мы определяем общие настройки подключения к БД. В остальных секциях, мы указываем различные БД и реквизиты доступа, в зависимости от типа секции. Итак, на каждую стадию разработки приложения, такие как непосредственная разработка, тестирование, пуск в эксплуатацию у нас есть своя БД (или несколько, если требуется работать с несколькими БД одновременно).
Видели в конфиге ресурс dbs? Да, у нас нет такого ресурса. Придется его создать. Я взял этот код с сайта blog.keppens.biz.
Вот, как выглядит ресурс, дающий нам возможность работать с несколькими БД:
/**
* 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 Project_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;
}
}
Теперь, в нашем файле Bootstrap, нам нужно запустить наш ресурс:
class Project_Application_Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
/**
* Initialize connections to multiple db's
*
* @return void
*/
protected function _initDbs()
{
$this->bootstrap('dbs');
$dbs = $this->getPluginResource('dbs');
Zend_Registry::set('db', $dbs->getDbAdapter('db1'));
Zend_Registry::set('db2', $dbs->getDbAdapter('db2'));
return $dbs;
}
}
Как видно, мы поместили адаптеры БД в реестр, откуда можем получить их в любой части приложения. По-умолчанию будет использоваться адаптер №1 - db, мы указали это в конфиге при помощи опции isDefaultTableAdapter. То есть, например, Zend_Db_Table по-умолчанию будет работать именно с первым адаптером.
Это все, что вам нужно сделать, чтобы работать с несколькими БД в Zend Framework.
Спрашивайте в комментах, если что-то непонятно.
Also interesting
Tags: zend framework, Zend_Db, Zend_Db_Table
Вы показали как сделать несколько подключений, но неправильно сказали про метод их применения.
Из вашего конфига видно, что разные подключения вы используете для разного окружения: test, development, production. Для этого нет необходимости создавать несколько подключений, достаточно при инициализации указать какой тип бд использовать.
В общем интересует вопрос зачем вам несколько подключений?
И как происходит выбор необходимого подключения (адаптера) в модели?
Ярослав, что-то не очень понятно, о чем вы.
О том, что плохо создавать сразу несколько подключений в бутстрапе?
В общем, расскажите, пожалуйста, подробнее.
Ты пишешь:
В общей секции (bootstrap) мы определяем общие настройки подключения к БД. В остальных секциях, мы указываем различные БД и реквизиты доступа, в зависимости от типа секции. Итак, на каждую стадию разработки приложения, такие как непосредственная разработка, тестирование, пуск в эксплуатацию у нас есть своя БД.
Однако расказываешь о другом, о работе с двумя объектами подключения бд. На каждую стадию разработки приложения у нас допустим и своя бд но объект то один и тотже. Поэтому ваще обычно люди ограничиваются различными секциями в конфигурационном файле.
Типа (кусок аппликейшн ини)
[production]
;
; Database initialization
;
resources.db.adapter = “PDO_MYSQL”
resources.db.params.host = “mysql.notes-notes.com”
resources.db.params.dbname = “notes”
resources.db.params.username = “notes-notes”
resources.db.params.password = “supersecretpass”
[development : production]
;
; For development, we want to display errors and use other database
;
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
phpSettings.error_reporting = E_ALL
resources.db.params.host = “mysql.dev.notes-notes.com”
resources.db.params.dbname = “devnotes”
resources.db.params.username = “lcf”
resources.db.params.password = “iamadeveloper”
***
Хотя в принципе два подключения то допустим и могут понадобится, ситуация вполне реальная, когда например просто приложение работает с разными уже существующими бд или чо нить в этом духе, так что пост вполне может быть полезен, но аргументация не правильная.
Да, я понял что вам не понравилось. На самом деле, такой разбитый на несколько “сред” ini-конфиг я привел лишь для того, чтобы продвигать правильный стиль разработки в массы. Я мог, конечно, обойтись и одной секцией, чтобы показать, как работать с несколькими БД одновременно.
Пост я подправил немного.