I am writing an application which requires the Master/Slave switch to happen inside the application layer. As it is right now, I instantiate a Zend_Db_Table object on creation of the mapper, and then setDefaultAdapter to the slave.
Now inside of the base mapper classe, I have the following method:
public function useWriteAdapter()
{
if(Zend_Db_Table_Abstract::getDefaultAdapter() != $this->_writeDb)
{
Zend_Db_Table_Abstract::setDefaultAdapter($this->_writeDb);
$this->_tableGateway = new Zend_Db_Table($this->_tableName);
}
}
I need a sanity check on this. I don't think the overhead is too much, I just suspect there must be a better way.
An object of type Zend_Db_Table_Row_Abstract
remembers what Table object produced it. But you can change the associated Table before you call save()
.
$readDb = Zend_Db::factory(...); // slave
$writeDb = Zend_Db::factory(...); // master
Zend_Db_Table::setDefaultAdapter($readDb);
$myReadTable = new MyTable(); // use default adapter
$myWriteTable = new MyTable($writeDb);
$row = $myTable->find(1234)->current();
$row->column1 = 'value';
$row->setTable($myWriteTable);
$row->save();
How about something like a base class that you extend which performs the startup?
class My_Db_Table extends Zend_Db_Table
{
function init()
{
if (....) {
// set the default adaptor to the write-DB-master
}
parent::init();
}
}
// all your models then extend My_Db_Table instead of Zend_Db_Table
I have found this article which I think will answer your question :)
Although you most probably already came up with a solution I will still post the way I did it:
I was looking for a solution for the same problem and came up with the idea to put the logic for that into the Adapter.
I extended the Zend_Db_Adapter_Abstract and added the boolean attribute $writes. I added public getter and setter methods for it as well.
My adapter saves two different database-configurations/-connections: one for the master (for writing) and one for the slave (for reading). (Actually it's not one configuration but many so I have kind of a pool of masters and salves which are selected randomly by weight.)
Now I do the following: Before I execute a query $writes must be set to true or false. In the method connect() the adapter connects or uses the right connection depending on the value of $writes.