Thanks much. I didn't realize the old (and easy) method of doing this was deprecated.
On Jan 19, 10:04 am, Andreas Hofmann <[email protected]> wrote: > Hi all, > > we have discovered a way how to realize master/slave support with cake > (also with multiple slaves). > This old post is completely > depricated:http://groups.google.com/group/cake-php/browse_thread/thread/58ea010f... > Because Model::find() and Model::save() create the $db-handle lines > before it calles the callbacks 'beforeFind' and 'beforeSave'. > > The way we realized is to overwrite the save() and updateAll() > methodes and to set the default db-config in the AppModel::__construct > (). > > Note: One thing remains: It's not possible to do a bindModel in the > 'beforeSave' and 'afterSave' callbacks, because they get the wrong db- > config... If you find a way to do it, please let us know! > > 1. Define your Database-Configs in app/config/database.php. You should > have master and as much slaves you want to have: > > class DATABASE_CONFIG { > > var $master = array( > driver' => 'mysql', > 'persistent' => false, > 'host' => 'localhost', > 'login' => 'login', > 'password' => 'password', > 'database' => 'database', > 'encoding' => 'utf8' > ); > > // Config for Slave #1 > var $slave1 = array( > driver' => 'mysql', > 'persistent' => false, > 'host' => 'slave1', > 'login' => 'login', > 'password' => 'password', > 'database' => 'database', > 'encoding' => 'utf8' > ); > > // Config for Slave #2 > var $slave2 = array( > driver' => 'mysql', > 'persistent' => false, > 'host' => 'slave2', > 'login' => 'login', > 'password' => 'password', > 'database' => 'database', > 'encoding' => 'utf8' > ); > ... > > } > > 2. Create/Alter app/models/app_model.php and create/alter the > constructor '__construct' of it like the following: > > class AppModel extends Model { > > public function __construct($id = false, $table = null, $ds = null) > { > > /********************************** > * USED FOR MASTER/SLAVE MECHANIC * > **********************************/ > // If a datasource is set via params, use it and return > if((is_array($id) && isset($id['ds'])) || $ds) { > parent::__construct($id, $table, $ds); > > return; > } > > // Use a static variable, to only use one connection per page-call > (otherwise we would get a new handle every time a Model is created) > static $_useDbConfig; > if(!isset($_useDbConfig)) { > // Get all available database-configs > $sources_list = ConnectionManager::enumConnectionObjects(); > > // Find the slaves we have > $slaves = array(); > foreach($sources_list as $name => $values) { > // Slaves have to be named "slave1", "slave2", etc... > if(preg_match('/^slave[0-9]+$/i', $name) == 1) { > $slaves[] = $name; > } > } > > // Randomly use a slave > $_useDbConfig = $slaves[rand(0, count($slaves) - 1)]; > $this->_usedSlave = $_useDbConfig; > } > $this->useDbConfig = $_useDbConfig; > > parent::__construct($id, $table, $ds); > } > ... > > } > > This method uses a local static variable to save the db-config > application-wide. It collects all configs from the database.php that > start with "slave#" and selects a random one for it. This is now the > "default"-config for the application that is used with every query > done via the Model-class UNTIL we do the next step: > > 3. We now overwrite the Model::save() and Model::find() methods to use > another database-config for write-queries! > Note: We discovered, that it's not enough to just overwrite Model::save > (), because Model::updateAll() doesn't use the callbacks, neither the > Model::save() method. > > function save($data = null, $validate = true, $fieldList = array()) > { > // Remember the old config > $oldDb = $this->useDbConfig; > // Set the new config > $this->setDataSource('master'); > // Call the original Model::save() method > $return = parent::save($data, $validate, $fieldList); > // Reset the config/datasource > $this->setDataSource($oldDb); > > return $return; > } > > function updateAll($fields, $conditions = true) { > $oldDb = $this->useDbConfig; > $this->setDataSource('master'); > $return = parent::updateAll($fields, $conditions); > $this->setDataSource($oldDb); > > return $return; > } > > Now you should have full master/slave support within your cake- > application. > The way it works: > When your application is called, the AppModel will be called the first > time and realizes, that the local $_useDbConfig variable is not set. > So it randomly selects one of your slave-configs and sets this to the > default used database-config (AppModel::useDbConfig). Every further > instance of AppModel will recognize that the local $_useDbConfig > variable already exists and will use the same config. > Now every query you do will use this slave-config, EXCEPT all save's > and updateAll's, because you've overwritten these methods to use your > master-config. > > Hope this tutorial was helpful to you! > > Greetings, > > Andreas Hofmann! --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "CakePHP" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/cake-php?hl=en -~----------~----~----~----~------~----~------~--~---
