Friday, May 6, 2016

Magento Multiple Database Connection

Working with Magento 1.9 I was asked to make multiple read and write connections.
Magento has the possibility to configure read and write connections in the /app/etc/local.xml. Just set the tag use to let Magento know which one is available.

<!-- MASTER SERVER -->
<default_setup>
     <connection>
         <host>master</host>
         <username>user</username>
         <password>123456</password>
         <dbname>magento</dbname>
         <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
         <model><![CDATA[mysql4]]></model>
         <type><![CDATA[pdo_mysql]]></type>
         <pdoType><![CDATA[]]></pdoType>
         <active>1</active>
     </connection>
</default_setup>
<default_write>
     <connection>
          <use>default_setup</use>
      </connection>
</default_write>
<!-- SLAVE SERVER -->
<slave_connection>
     <connection>
           <host>slave</host>
           <username>user</username>
           <password>123456</password>
           <dbname>magento</dbname>
           <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
           <model><![CDATA[mysql4]]></model>
           <type><![CDATA[pdo_mysql]]></type>
           <pdoType><![CDATA[]]></pdoType>
           <active>1</active>
      </connection>
</slave_connection>
<default_read>
      <connection>
          <use>slave_connection</use>
      </connection>
</default_read>

We can define n connections in the same config file like this test example

 
   
   test_server
   root
   123456
   magento_db
   SET NAMES utf8
   mysql4
   pdo_mysql
   
   1
 

The limit is that the connections are applied to the whole system but my idea is to set only for certain resources.
In this case I have a custom report module where I only want to make read connections in the Order table.
After overriding the Order resource Mage/Sales/Model/Resource/Order.php
Just make 3 updates

  1. Make a flag to know if its time to change the connection $reportConnection.
  2. Update function _construct() to create the custom connection and add it to the array of resources.
  3. Update function _getConnection() to decide if use the custom connection.

//flag
public $reportConnection = false;

/**
*Just add the connection defined in the local.xml 'test_read'
*/
protected function _construct(){
    $this->_init('sales/order', 'entity_id');
    $this->_resources->getConnection('test_read');
}

/**
*Make the connection if the flag is set
*/
protected function _getConnection($connectionName){
 if (isset($this->_connections[$connectionName])) {
   return $this->_connections[$connectionName];
    }

   if($connectionName == 'read' && $this->reportConnection)
        $this->_connections[$connectionName] = $this->_resources->getConnection('test_read');
   else{
   if (!empty($this->_resourcePrefix)) {
      $this->_connections[$connectionName] = $this->_resources->getConnection(
      $this->_resourcePrefix . '_' . $connectionName);
  } else {
   $this->_connections[$connectionName] = $this->_resources->getConnection($connectionName);
  }
   }
   return $this->_connections[$connectionName];
}

Last step is to make call an Order collection but using the test_read connection.
//Get the Order model
$model = Mage::getModel('sales/order');
//set the flag
$model->getResource()->reportConnection = true;
//get the collection
$collection = $model->getCollection();