Magento использует модели для работы с данными, это обеспечивает удобный доступ к ним и обработку. Используя грамотно именованные методы и "умную" абстракцию, Varien скрывает от нас сложную SQL реализацию необходимую для операций с данными.

Это делает изучение моделей проще, увеличивает скорость операций и повышает скорость отклика сайта. Это особенно справедливо когда речь идет о моделях использующих EAV архитектуру. Однако, есть ситуации когда прямые SQL запросы могут быть быстрее и проще. Как пример можно привести массовое обновление товарных цен. Достаточно легко написать код который будет пробегаться по всем товарам и пересчитывать цены. В то время как отдельная правка каждого продукта, при большом массиве данных, будет занимать очень много времени. Чтобы это побороть, можно использовать прямые SQL запросы, что позволит обновить 1000 продуктов за 1-2 секунды.

Подключение к БД в magento.

По умолчанию magento автоматически подключается к базе данных и обеспечивает два независимых ресурса доступа к данным: core_read и core_write. Как вы можете догадаться, первый используется для чтения из БД, а второй для записи. Это особенно важно, убедиться что используется правильный ресурс, особенно при создании модулей, которые разойдутся по всему миру.

<?php   
    /**
     * Получение ресурсной модели
     */
    $resource = Mage::getSingleton('core/resource');
 
    /**
     * Установка соединения для чтения
     */
    $readConnection = $resource->getConnection('core_read');
 
    /**
     * Установка соединения для записи
     */
    $writeConnection = $resource->getConnection('core_write');

Названия таблиц и префиксы

При установке magento, можно задать опцию использовать префиксы в таблицах или нет. Префикс - это строка символов, которая добавляется в начало имени таблицы БД. Это полезно, если вы устанавливаете множественную систему в которой нужно изолировать данные приложений друг от друга. К счастью, magento имеет встроенную функцию добавления префикса к имени определенной таблицы.

Получения названия таблицы из строки

<?php
    /**
     * Получение ресурсной модели
     */
    $resource = Mage::getSingleton('core/resource');
 
    /**
     * Получение имени таблицы
     */
    $tableName = $resource->getTableName('catalog_product_entity');
 
    /**
     * Если префикс был 'mage_' то на выходе
     * мы получим mage_catalog_product_entity
     */
    echo $tableName;

Получение названия таблицы из названия entity-сущности

<?php
 
    /**
     * Получение ресурсной модели
     */
    $resource = Mage::getSingleton('core/resource');
 
    /**
     * Получение имени таблицы
     */
    $tableName = $resource->getTableName('catalog/product');
 
    /**
     *Если префикс был 'mage_' то на выходе
     * мы получим mage_catalog_product_entity
     */
    echo $tableName;

Чтение из БД

Хотя модели magento скрывают всю сложность EAV системы, они иногда запрашивают гораздо больше данных, чем нужно. Например, если у вас есть product ID и вы хотите его SKU, будет гораздо быстрее сделать простой запрос чем грузить целиком модель продукта.

метод Varien_Db_Select::fetchAll

Метод принимает запрос в качестве параметра, и возвращает результаты в качестве массива.

<?php
 
    /**
     * Поучение ресурсной модели
     */
    $resource = Mage::getSingleton('core/resource');
 
    /**
     * Установка соединения для чтения
     */
    $readConnection = $resource->getConnection('core_read');
 
    $query = 'SELECT * FROM ' . $resource->getTableName('catalog/product');
 
    /**
     * Выполнение запроса и сохранение результата в $results
     */
    $results = $readConnection->fetchAll($query);
 
    /**
     * Вывод результатов
     */
     var_dump($results);

метод Varien_Db_Select::fetchCol

Этот метод похож на fetchAll за тем исключением что он возвращает первый элемент из каждой результирующей колонки. В коде примера ниже, мы используем Varien_Db_Select::fetchCol для получения всех SKU из базы в виде массива.

<?php
    /**
      * Получение ресурсной модели
      */
    $resource = Mage::getSingleton('core/resource');
 
    /**
     * Установка соединения для чтения
     */
    $readConnection = $resource->getConnection('core_read');
 
    /**
     * Получение имени таблицы
     */
    $table = $resource->getTableName('catalog/product');
 
    /**
     * Выполнение запроса и сохранение результатов в $results
     */
    $sku = $readConnection->fetchCol('SELECT sku FROM ' . $table . ');
 
    /**
     * Вывод результатов
     */
     var_dump($results);

Попробуйте оба метода и вы поймете разницу. fechCol возвращает все значения в едином массиве, тогда как значения SKU полученные методом fetchAll находятся каждое в отдельном подмассиве.

метод Varien_Db_Select::fetchOne

В отличие от предыдущих двух методов Varien_Db_Select::fetchOne возвращает только первое значение из первой колонки результатов. Оно не обернуто в массив. В примере мы получили SKU для продукта с ID равным 44.

<?php
 
    /**
     * Получение ресурсной модели
     */
    $resource = Mage::getSingleton('core/resource');
 
    /**
     * Установка соединения для чтения
     */
    $readConnection = $resource->getConnection('core_read');
 
    /**
     * Получение имени таблицы
     */
    $table = $resource->getTableName('catalog/product');
 
    /**
     * Установка product ID
     */
    $productId = 44;
 
    $query = 'SELECT sku FROM ' . $table . ' WHERE entity_id = '
             . (int)$productId . ' LIMIT 1';
 
    /**
     * Выполнение запроса и запись результата в $sku
     */
    $sku = $readConnection->fetchOne($query);
 
    /**
     * Вывод SKU на экран
     */
    echo 'SKU: ' . $sku . '<br/>';

Запись в БД

Когда в БД сохраняется модель, происходит передача множества данных, даже таких, о которых вы могли быть не в курсе. Как пример, сохранение модели продукта может занять пару секунд из-за большого количества связанных данных и индексации. Это приемлемо, если вы хотите сохранить все данные о продукте, но если нужно только обновить артикул, это выглядит расточительно.

На следующем примере можно будет понять, как по известному ID продукта можно изменить его артикул.

    <?php
 
    /**
     * Получение ресурсной модели
     */
    $resource = Mage::getSingleton('core/resource');
 
    /**
     * Установка соединения для записи
     */
    $writeConnection = $resource->getConnection('core_write');
 
    /**
     * Получение имени таблицы
     */
    $table = $resource->getTableName('catalog/product');
 
    /**
     * Установка product ID
     */
    $productId = 10;
 
    /**
     * Установка нового значения SKU
     * 
     * Если  если входные данные являются статическими, рассмотрите возможность
     * использования объекта Varien_Db_Select  для вставки данных
     */
    $newSku = 'new-sku';
 
    $query = "UPDATE {$table} SET sku = '{$newSku}' WHERE entity_id = "
             . (int)$productId;
 
    /**
     * Выполнение запроса
     */
    $writeConnection->query($query);

Для тестирования используйте ранее рассмотренный метод вывода одного единственного значения

Varien_Db_Select

Varien_Db_Select, затронутый в этом примере - это еще одна очень удобная опция для извлечения/записи информации. Не только из-за простоты использования, но также по причине обеспечения уровневой безопасности, которая, будучи грамотно применена, являться непроницаемой. Более подробно Varien_Db_Select (он же Zend_Db_Select) будет рассмотрен в следующих статьях.

Заключение

Иногда прямые SQL запросов в Magento необходимы, однако пожалуйста, будьте осторожны!!! Magento модели существует в том числе по причине обеспечения слоя безопасности, который вам придется вручную добавить в свой собственный прямой SQL запрос. Будьте уверены, что недопустите любого пользовательского вмешательства, и, когда это возможно, придерживайтесь методов моделей Magento! Если вы не можете придерживаться моделей Magento , рассмотрите возможность использования Varien_Db_Select, это не убережет вас от ошибок, но это добавит почти непроницаемый слой безопасности ваших запросов к базе данных.