Skip to content

Instantly share code, notes, and snippets.

@lstrojny
Created March 25, 2011 19:31
Show Gist options
  • Save lstrojny/887460 to your computer and use it in GitHub Desktop.
Save lstrojny/887460 to your computer and use it in GitHub Desktop.
<?php
namespace Jarlssen\Doctrine2\DBAL;
use Doctrine\DBAL\Connection,
Doctrine\DBAL\Driver,
Doctrine\ORM\Configuration,
Doctrine\Common\EventManager,
Doctrine\DBAL\Events;
class MasterSlaveConnection extends Connection
{
/**
* Master connection
*
* @var Doctrine\DBAL\Driver\Connection
*/
protected $_masterConn;
/**
* Slave connection
*
* @var Doctrine\DBAL\Driver\Connection
*/
protected $_slaveConn;
public function __construct(
array $params,
Driver $driver,
Configuration $config = null,
EventManager $eventManager = null
)
{
if (!isset($params['slaves']) or !isset($params['master'])) {
throw new \InvalidArgumentsException('master or slaves configuration missing');
}
$params['master']['driver'] = $params['driver'];
foreach ($params['slaves'] as &$slave) {
$slave['driver'] = $params['driver'];
}
parent::__construct($params, $driver, $config, $eventManager);
}
public function connect($connectionName = 'slave')
{
$forceMasterAsSlave = false;
if ($this->getTransactionNestingLevel() > 0) {
$connectionName = 'master';
$forceMasterAsSlave = true;
}
$connectionProperty = '_' . $connectionName . 'Conn';
if ($this->{$connectionProperty}) {
if ($forceMasterAsSlave) {
$this->_slaveConn = $this->_conn = $this->_masterConn;
} else {
$this->_conn = $this->{$connectionProperty};
}
return false;
}
if ($connectionName === 'master') {
/** Set master and slave connection to master to avoid invalid reads */
$this->_masterConn = $this->_slaveConn = $this->_conn = $this->_connectTo($connectionName);
} else {
$this->_slaveConn = $this->_conn = $this->_connectTo($connectionName);
}
if ($this->_eventManager->hasListeners(Events::postConnect)) {
$eventArgs = new Event\ConnectionEventArgs($this);
$this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs);
}
return true;
}
protected function _connectTo($connectionName)
{
$params = $this->getParams();
$driverOptions = isset($params['driverOptions']) ? $params['driverOptions'] : array();
$connectionParams = $this->_chooseConnectionConfiguration($connectionName, $params);
$user = isset($connectionParams['user']) ? $connectionParams['user'] : null;
$password = isset($connectionParams['password']) ? $connectionParams['password'] : null;
return $this->_driver->connect($connectionParams, $user, $password, $driverOptions);
}
protected function _chooseConnectionConfiguration($connectionName, $params)
{
if ($connectionName === 'master') {
return $params['master'];
}
return $params['slaves'][array_rand($params['slaves'])];
}
public function executeUpdate($query, array $params = array(), array $types = array())
{
$this->connect('master');
return parent::executeUpdate($query, $params, $types);
}
public function beginTransaction()
{
$this->connect('master');
return parent::beginTransaction();
}
public function commit()
{
$this->connect('master');
return parent::commit();
}
public function rollback()
{
$this->connect('master');
return parent::rollback();
}
public function delete($tableName, array $identifier)
{
$this->connect('master');
return parent::delete($tableName, $identifier);
}
public function update($tableName, array $data, array $identifier)
{
$this->connect('master');
return parent::update($tableName, $data, $identifier);
}
public function insert($tableName, array $data)
{
$this->connect('master');
return parent::insert($tableName, $data);
}
public function exec($statement)
{
$this->connect('master');
return parent::exec($statement);
}
public function getWrappedConnection()
{
$this->connect('master');
return $this->_conn;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment