Les requêtes SQL directes dans Magento

  • De le 30 juillet 2012
  • Difficulté : 2/4

Les requêtes SQL directes dans Magento Les modèles de données sont un excellent moyen pour accéder aux informations en base. Cela évite la rédaction de requêtes souvent complexes. Mais dans certains cas, il est intéressant d'utiliser une requête directe.

Nous utilisons régulièrement les modèles de données de Magento pour accéder aux enregistrements stockés en base. Les requêtes SQL sont automatiquement générées. Cependant, l'utilisation des modèles a un impact sur les vitesses d'exécution. Dans certaines situations, utiliser directement une requête est beaucoup plus rapide : une mise à jour globale des prix par exemple. Une simple requête peut permettre la mise à jour de 1000 produits en 1 ou 2 secondes.

Attention :

La base de données de Magento évolue régulièrement. Une requête "maison" ne fonctionnera peut être plus demain lors d'une mise à jour. C'est pourquoi elles sont à utiliser dans des cas très particuliers.

Elles peuvent faciliter la vie si vous devez temporairement accéder à un grand nombre d'informations (pour un export particulier par exemple), ou pour mettre à jour un nombre important de données.

L'utilisation des requêtes demande également une bonne connaissance de la base de données Magento. Prenez garde lors des écritures...

Connexion à la base de données

Magento fournit par défaut 2 connexions distinctes : core_read et core_write.

  • core_read : lecture dans la base de données
  • core_write : écriture dans la base de données

Il faut veiller à utiliser la bonne connexion : core_write pour écrire en base (DELETE, UPDATE, INSERT...), core_read pour la lecture (SELECT).

La configuration d'une base de données pour une connexion de type core_read et core_write pourrait éventuellement être différente. On pourrait imaginer configurer plusieurs utilisateurs de connexion à la base.

Un module pourrait aussi utiliser une base de données différente. Par exemple un module de log dont la connexion serait logs_write.

Pour instancier les connexions :

Magento Connection Access

<?php
$resource = Mage::getSingleton('core/resource');
 
$readConnection = $resource->getConnection('core_read');
 
$writeConnection = $resource->getConnection('core_write');

$readConnection et $writeConnection sont des objets de la classe Varien_Db_Adapter_Pdo_Mysql.

Nom des tables et préfixe des tables

Lors de l'installation, Magento nous propose d'utiliser un préfixe de table. Pour utiliser le module sur différentes plateformes, il nous faut récupérer le nom d'une table avec son préfixe. Pour cela nous utilisons la méthode getTableName :

Méthode getTableName avec le nom d'une table

<?php
$resource = Mage::getSingleton('core/resource');
 
$tableName = $resource->getTableName('catalog_product_entity');
 
echo $tableName; // <prefix>catalog_product_entity

Il est également possible de récupérer le nom d'une table avec le nom de l'entité :

Méthode getTableName avec le nom d'une entité

<?php
$resource = Mage::getSingleton('core/resource');

$tableName = $resource->getTableName('catalog/product');
 
echo $tableName;  // <prefix>catalog_product_entity

Lecture dans la base de données

Les modèles de données Magento masquent la complexité des requêtes SQL. Le modèle EAV oblige l'utilisation de nombreuses jointures (voir l'article Base de données Magento : comprendre le modèle EAV).

Si vous souhaitez simplement récupérer le sku d'un produit en fonction de son id, il est plus rapide de l'obtenir par une simple requête, plutôt que de charger le modèle de données produit dans son intégralité.

fetchAll

Cette méthode exécute une requête passée en paramètre, puis retourne les résultats dans un tableau.

fetchAll

$resource = Mage::getSingleton('core/resource');
 
$readConnection = $resource->getConnection('core_read');

$query = 'SELECT * FROM ' . $resource->getTableName('catalog/product');

$products = $readConnection->fetchAll($query);

Zend_debug::dump($products);

// array(3) {
//  [0] => array(10) {
//    ["entity_id"] => string(1) "3"
//    ["entity_type_id"] => string(1) "4"
//    ["attribute_set_id"] => string(2) "35"
//    ["type_id"] => string(6) "simple"
//    ["sku"] => string(12) "SKU01"
//    ["category_ids"] => string(3) "200"
//    ["created_at"] => string(19) "2009-06-02 13:19:21"
//    ["updated_at"] => string(19) "2011-04-14 10:03:16"
//    ["has_options"] => string(1) "0"
//    ["required_options"] => string(1) "0"
//  }
//  [1] => array(10) {
//     (...)
//  }
// }

fetchCol

Cette méthode est similaire à fetchAll mais ne retourne que la première colonne de chaque ligne. Dans l'exemple ci-dessous, nous utilisons fetchCol pour récupérer l'ensemble des Sku des produits :

fetchCol

<?php
$resource = Mage::getSingleton('core/resource');
 
$readConnection = $resource->getConnection('core_read');
 
$table = $resource->getTableName('catalog/product');
 
$sku = $readConnection->fetchCol('SELECT sku FROM ' . $table);

Zend_debug::dump($sku);

// array(4) {
//  [0] => string(5) "SKU01"
//  [1] => string(5) "SKU02"
//  [2] => string(5) "SKU03"
//  [3] => string(5) "SKU04"
// }

fetchOne

fetchOne retourne une valeur de la première ligne. Dans l'exemple ci-dessous, nous obtenons le nombre de produits enregistrés en base :

fetchOne

$resource = Mage::getSingleton('core/resource');

$readConnection = $resource->getConnection('core_read');

$table = $resource->getTableName('catalog/product');

$query = 'SELECT COUNT(*) FROM '.$table.' LIMIT 1';

$count = $readConnection->fetchOne($query);

echo $count.' products'; // <nb> products

Autres méthodes

D'autres méthodes sont à notre disposition : fetchAssoc, fetchPairs et fetchRow.

fetchAssoc

$query = 'SELECT sku,entity_id FROM catalog_product_entity';

$result = $readConnection->fetchAssoc($query);

// array(3) {
//   ["SKU01"] => array(2) {
//     ["sku"] => string(5) "SKU01"
//     ["entity_id"] => string(2) "20"
//   }
//   ["SKU02"] => array(2) {
//     ["sku"] => string(5) "SKU02"
//     ["entity_id"] => string(2) "21"
//   }
//   ["SKU03"] => array(3) {
//     ["sku"] => string(5) "SKU32"
//     ["entity_id"] => string(2) "22"
//   }
// }

fetchPairs

$query = 'SELECT sku,entity_id FROM catalog_product_entity';

$result = $readConnection->fetchPairs($query);

// array(3) {
//   ["SKU01"] => string(2) "20"
//   ["SKU02"] => string(2) "21"
//   ["SKU03"] => string(2) "22"
// }

fetchRow

$query = 'SELECT * FROM catalog_product_entity';

$result = $readConnection->fetchRow($query);

// array(10) {
//  ["entity_id"] => string(2) "20"
//  ["entity_type_id"] => string(1) "4"
//  ["attribute_set_id"] => string(2) "35"
//  ["type_id"] => string(6) "simple"
//  ["sku"] => string(12) "SKU01"
//  ["category_ids"] => string(3) "200"
//  ["created_at"] => string(19) "2009-06-02 13:19:21"
//  ["updated_at"] => string(19) "2011-04-14 10:03:16"
//  ["has_options"] => string(1) "0"
//  ["required_options"] => string(1) "0"
// }

Ecriture dans la base de données

L'exemple ci-dessous permet de modifier le sku d'un produit en fonction de son id.

Update Data

<?php
$resource = Mage::getSingleton('core/resource');
 
$writeConnection = $resource->getConnection('core_write');
 
$table = $resource->getTableName('catalog/product');
 
$productId = 1;

$newSku = 'NEWSKU';
 
$query = "UPDATE ".$table." SET sku = '".$sku."' WHERE entity_id = ".(int)$productId;
 
$writeConnection->query($query);
commentaires

Commentez cet article : Les requêtes SQL directes dans Magento