Question

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.

Was it helpful?

Solution

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();

OTHER TIPS

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top