[Magento] 在 .xml 文件中配置模块数据库连接

今天花了点时间研究了一下 Magento 创建数据库连接的代码,不得不说 Magento 的配置系统的确强大,通过简单的 .xml 配置,就可以实现拆分数据库、读写分离,非常方便,而且日后查看一目了然。

以 Jp_Proposal 模块为例:
具体配置代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
file: app/code/local/Jp/Proposal/etc/config.xml
<resources>
    <jp_proposal_setup>
                <setup>
                    <module>Jp_Proposal</module>
                </setup>
                <connection>
                    <host>localhost</host>
                    <username>username</username>
                    <password>password</password>
                    <dbname>database_name</dbname>
                    <model>mysql4</model>
                    <initStatements>SET NAMES utf8</initStatements>
                    <type>pdo_mysql</type>
                    <active>1</active>
                </connection>
            </jp_proposal_setup>
            <jp_proposal_read>
                <connection>
                    <host>localhost</host>
                    <username>username</username>
                    <password>password</password>
                    <dbname>database_name</dbname>
                    <model>mysql4</model>
                    <initStatements>SET NAMES utf8</initStatements>
                    <type>pdo_mysql</type>
                    <active>1</active>
                </connection>
            </jp_proposal_read>
            <jp_proposal_write>
                <connection>
                    <host>localhost</host>
                    <username>username</username>
                    <password>password</password>
                    <dbname>database_name</dbname>
                    <model>mysql4</model>
                    <initStatements>SET NAMES utf8</initStatements>
                    <type>pdo_mysql</type>
                    <active>1</active>
                </connection>
            </jp_proposal_write>
</resources>

通过以上简单配置,Jp_Proposal 模块的 setup, read, write 三种数据库连接都会以上面的配置信息初始化,达到分库、读写分离的目的。

Magento 中生成数据库连接的代码位于 Resource 的基类: Mage_Core_Model_Resource

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
 * Creates a connection to resource whenever needed
 *
 * @param string $name
 * @return Varien_Db_Adapter_Interface
 */

public function getConnection($name)
{
    if (isset($this->_connections[$name])) {
        $connection = $this->_connections[$name];
        if (isset($this->_skippedConnections[$name]) && !Mage::app()->getIsCacheLocked()) {
            $connection->setCacheAdapter(Mage::app()->getCache());
            unset($this->_skippedConnections[$name]);
        }
        return $connection;
    }
    $connConfig = Mage::getConfig()->getResourceConnectionConfig($name);

    if (!$connConfig) {
        $this->_connections[$name] = $this->_getDefaultConnection($name);
        return $this->_connections[$name];
    }
    if (!$connConfig->is('active', 1)) {
        return false;
    }

    $origName = $connConfig->getParent()->getName();
    if (isset($this->_connections[$origName])) {
        $this->_connections[$name] = $this->_connections[$origName];
        return $this->_connections[$origName];
    }

    $connection = $this->_newConnection((string)$connConfig->type, $connConfig);
    if ($connection) {
        if (Mage::app()->getIsCacheLocked()) {
            $this->_skippedConnections[$name] = true;
        } else {
            $connection->setCacheAdapter(Mage::app()->getCache());
        }
    }

    $this->_connections[$name] = $connection;
    if ($origName !== $name) {
        $this->_connections[$origName] = $connection;
    }

    return $connection;
}

在上面代码中,以 Jp_Proposap 模块 read 为例, $name = ‘jp_proposal_read’。
在初始化数据库连接时,先去配置文件里面查找 global -> resources -> jp_proposal_read 节点,如果可以找到这个节点,就以其中的配置信息初始化数据库连接并返回此数据库连接; 如果没有找到这个节点(节点不存在),则使用 Magento 默认的 core_read 的配置信息来初始化数据库连接并返回此连接。