Зовнішнє підключення до бази даних в Magento

Table of Content

Не часто виникає необхідність підключення до зовнішньої бази даних з Magento. Але коли така необхідність з’являється краще бути підготовленим, ніж витрачати години на вирішення питання. Як казав мій вчитель англійської: “Краще тупий олівець, ніж гостра пам’ять.”

Виникла необхідність вивести на головній сторінці Magento декілька записів з іншої бази даних. Наче нічого складного, а правильна реалізація вимагає відповідального підходу до виконання.
По великому рахунку з CRUD (create, read, update, delete) потрібна тільки буква “R”.
Є декілька способів підключитись до зовнішньої бази даних з Magento, в даній статі буде розглянутий один з них, який дає можливість використовувати весь функціонал системи.

Конфігурація

Налаштування відбувається в загальній XML конфігурація, так як і підключення за замовчуванням. Відмінність полягає в тому, що нам потрібно створити цю конфігурацію в окремому модулі. Де буде оголошено read та write адаптери, setup та піключення до зовнішньої бази даних. Зовнішні таблиці оголошуються так як і внутрішні таблиці Magento. Вони будуть знаходитись під popov_wp_resource, тому відповідну модель можна буде викликати пізніше в коді.

// app/code/community/Popov/Wp/etc/config.xml
<?xml version="1.0"?>
<config>
    <modules>
        <Popov_Wp>
            <version>0.1.0</version>
        </Popov_Wp>
    </modules>

    <global>

        <blocks>
            <popov_wp>
                <class>Popov_Wp_Block</class>
            </popov_wp>
        </blocks>

        <helpers>
            <popov_wp>
                <class>Popov_Wp_Helper</class>
            </popov_wp>
        </helpers>

        <models>
            <popov_wp>
                <class>Popov_Wp_Model</class>
                <resourceModel>popov_wp_resource</resourceModel>
            </popov_wp>
            <popov_wp_resource>
                <class>Popov_Wp_Model_Resource</class>
                <entities>
                    <post>
                        <table>wp_posts</table>
                    </post>
                </entities>
            </popov_wp_resource>
        </models>

        <resources>
            <popov_wp_write>
                <connection>
                    <use>popov_wp_database</use>
                </connection>
            </popov_wp_write>
            <popov_wp_read>
                <connection>
                    <use>popov_wp_database</use>
                </connection>
            </popov_wp_read>
            <popov_wp_setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </popov_wp_setup>

            <popov_wp_database>
                <connection>
                    <host><![CDATA[localhost]]></host>
                    <username><![CDATA[username]]></username>
                    <password><![CDATA[password]]></password>
                    <dbname><![CDATA[database]]></dbname>
                    <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
                    <model><![CDATA[mysql4]]></model>
                    <type><![CDATA[pdo_mysql]]></type>
                    <active>1</active>
                </connection>
            </popov_wp_database>
        </resources>

    </global>
</config>

Модель (Model)

Наступним кроком буде створення моделі, яка дасть змогу створити зовнішнє підключення і діставати або зберігати потрібні дані.
Дана модель буде працювати з таблицею wp_posts оголошеною в XML конфігурації, в даному випадку в таблиці зберігаються всі дописи блогу.

// app/code/community/Popov/Wp/Model/Post.php
class Popov_Wp_Model_Post extends Mage_Core_Model_Abstract
{
    protected function _construct()
    {
        $this->_init('popov_wp/post');
    }

}

Далі буде показано приклад як використовувати дану модель (діставати, відфільтрувати, сортувати дані і т.д.). Для того щоб зчитувати дані повинен, в першу чергу, бути визначений read адаптер. Він визначений в XML конфігурація як popov_wp_read.
Також обов’язково потрібно оголосити Resource, щоб мати можливість додавати і видаляти дані, та Collection, щоб працювати з колекціями.

// app/code/community/Popov/Wp/Model/Resource/Post.php
class Popov_Wp_Model_Resource_Post extends Mage_Core_Model_Resource_Db_Abstract
{
    protected function _construct()
    {
        $this->_init('popov_wp/post', 'ID');
    }
}
// app/code/community/Popov/Wp/Model/Resource/Post/Collection.php
class Popov_Wp_Model_Resource_Post_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
{
    protected function _construct()
    {
        $this->_init('popov_wp/post');
    }
}

Основні налаштування які пов’язані саме із зовнішнім підключенням до бази даних завершені. Далі буде показано приклад використання та додаткові налаштування для коректної роботи модулю.

Дістаємо записи

За допомогою нашої модель використовуємо загально прийнятий спосіб роботи з даними в Magento, а саме дістаємо дані, що нічим не відрізняється від інших моделей в системі. Модель сама визначить яке підключення їй використовувати на основі XML конфігурації.

// app/code/community/Popov/Wp/Block/Last.php
class Popov_Wp_Block_Last extends Mage_Core_Block_Template
{
    /**
     * @var Popov_Wp_Model_Post[]
     */
    protected $posts = [];

    public function getPosts()
    {
        if ($this->helper('popov_wp')->isEnabled() && !$this->posts) {
            $collection = Mage::getModel('popov_wp/post')->getCollection();

            $select = $collection->getSelect();

            $select->reset('columns');
            $select->columns('post_title');
            $select->columns('post_status');
            $select->columns('post_date');
            $select->columns('post_content');
            $select->columns('post_name');
            $select->columns(['post_guid' => 'guid']);
            $select->columns(['post_image' => '(SELECT `guid` FROM wp_posts WHERE id = m.meta_value)']);

            $select->joinLeft(
                ['m' => 'wp_postmeta'],
                'm.post_id = main_table.id',
                []
            );

            $select->where('main_table.post_status = ?', 'publish');
            $select->where('main_table.post_type = ?', 'post');
            $select->where('m.meta_key = ?', '_thumbnail_id');

            $select->limit($this->helper('popov_wp')->getNumberPostsOnHome());
            $select->order('post_date DESC');

            $this->posts = $collection;
        }

        return $this->posts;
    }
}

Коротко про те, що робить метод getPosts. Основна задача була дістати останні дописи з зовнішньої бази даних. Оригінальний запит виглядає ось так:

SELECT
    `main_table`.`post_title`,
    `main_table`.`post_status`,
    `main_table`.`post_date`,
    `main_table`.`post_content`,
    `main_table`.`post_name`,
    `main_table`.`guid` AS `post_guid`,
    (SELECT `guid` FROM wp_posts WHERE id = m.meta_value) AS `post_image`
FROM `wp_posts` AS `main_table` 
LEFT JOIN `wp_postmeta` AS `m` ON m.post_id = main_table.id
WHERE(main_table.post_status = 'publish')
    AND (main_table.post_type = 'post')
    AND (m.meta_key = '_thumbnail_id')
    ORDER BY `post_date` DESC
    LIMIT 5

Додаткові налаштування

Потрібно створити хелпер щоб уникнути незрозумілих помилок на етапі реалізації модулю

// app/code/community/Popov/Wp/Helper/Data.php
class Popov_Wp_Helper_Data extends Mage_Core_Helper_Abstract
{
    public function isEnabled()
    {
        return Mage::getStoreConfig('popov_wp/settings/enable');
    }
}

Для зручності рекомендується винести підключення до зовнішньої бази даних з модулю у app/etc/config.xml або створити новий app/etc/wp.xml з наступним вмістом:

<config>
    <global>
        <resources>
            <default_setup>
                <!-- ... -->
            </default_setup>
            <popov_wp_database>
                <connection>
                    <host><![CDATA[{{ wp_db_host }}]]></host>
                    <username><![CDATA[{{ wp_db_user }}]]></username>
                    <password><![CDATA[{{ wp_db_pass }}]]></password>
                    <dbname><![CDATA[{{ wp_db_name }}]]></dbname>
                    <initStatements><![CDATA[SET NAMES utf8]]></initStatements>
                    <model><![CDATA[mysql4]]></model>
                    <type><![CDATA[pdo_mysql]]></type>
                    <active>1</active>
                </connection>
            </popov_wp_database>
        </resources>
    </global>
</config>

Leave a Reply

Your email address will not be published. Required fields are marked *