Flux de données avec Magento. Les profils avancés

Sur un site marchand, il est fréquent d'importer des produits. Il peut s'agir d'imports "one shot", pour initialiser la boutique ou d'imports récurrents. La majorité des solutions e-commerce intègre des mécanismes d'imports. Ces solutions imposent un format et des données pré-formatées. Cependant, il peut arriver que les données à traiter ne correspondent pas aux modèles pré-définis. En complément des systèmes classiques, Magento permet facilement et rapidement l'intégration de fichiers spécifiques.

L'ajout d'un nouveau type d'import peut être réalisé en trois étapes

  • la description en XML du modèle d'import
  • la surcharge (optionnelle) de l’adaptateur
  • l'écriture d'une classe assurant le parsing des données.

Pour notre cas d'étude, nous prendrons l'exemple d'un fichier avec des champs de largeur fixe, pour une version 1.7.0.2 de Magento.

Création d'un profil d'importation

La première étape consiste à créer le XML décrivant l'import. L'action de création peut être effectuée depuis le back office.

Système > Importer/Exporter > Flux de données - Profils avancés

Le XML d'actions du profil est constitué de deux sections action.

<action type="dataflow/convert_adapter_io" method="load">
<var name="type">file</var>
<var name="path">PATH</var>
<var name="filename"><![CDATA[FICHIER]]></var>
<var name="format"><![CDATA[edi]]></var>
</action>
    <action type="dataflow/convert_parser_edi_adonix" method="parse">
<var name="map">
<map name="file_id">3</map>
<map name="product_id">10</map>
<map name="sku">10</map>
<map name="design1">30</map>
<map name="image1">64</map>
<map name="design2">30</map>
<map name="image2">64</map>
<map name="critsup">64</map>
<map name="critwrk">64</map>
<map name="prix">20</map>
<map name="tva">10</map>
<map name="qte">10</map>
<map name="id_parent">10</map>
<map name="nouveaute">3</map>
<map name="code_article_fournisseur">20</map>
<map name="flag_conso">3</map>
<map name="text">255</map>
</var>
<var name="store"><![CDATA[0]]></var>
<var name="number_of_records">1</var>
<var name="adapter">catalog/convert_adapter_product</var>
<var name="method">parse</var>
</action>

Exemple de fichier XML d'actions du profil

Nous allons maintenant regarder dans les détails les deux grandes sections qui composent ce XML

Section XML adaptateur

La première section va permettre de charger le fichier contenant les éléments à importer.
La balise action va définir les éléments pour charger le fichier. Elle contient les attributs suivants :

  • type : définit la classe
  • method : définit la méthode

Les nœuds var seront passés en paramètres lors de l'appel de la fonction

  • type : type de données, fichier dans notre cas
  • path : chemin vers le fichier
  • filename : nom du fichier
  • format : format du fichier

Section XML convertisseur

La seconde section du XMl va permettre de définir le convertisseur à utiliser, ainsi que les champs à importer.

La balise action va définir la classe et la méthode à utiliser pour parser le fichier. Elle contient les attributs suivants :

  • type, qui définit la classe
  • method, qui définit la méthode

Les nœuds var seront passés en paramètres lors de l'appel de la fonction.

  • map : table de correspondance entre la longueur des champs et les attributs du produit Magento. L'attribut map du XML va stocker l'attribut du produit Magento, tandis que les chiffres donnent la taille du champ. Par exemple :
    • file_id : 3 premiers caractères
    • product_id : les 10 caractères suivants
    • sku : les 10 caractères suivants
  • store : boutique pour l'import'
  • number_of_records : nombre de lignes traités simultanément
  • adapter : adaptateur utilisé pour enregistrer les produits
  • method : méthode utilisée pour importer les produits

Lors de la création de table de correspondance, si les attributs ne sont pas des attributs produits existants, ils seront tout simplement ignorés. L'attribut SKU, quant à lui, doit toujours être présent. Si le produit existe, il sera a mis à jour. Si non, il sera créé.

Surcharger l'adaptateur

Nous allons voir comment surcharger l'adaptateur pour ajouter une sauvegarde du fichier avant traitement. Si besoin, je vous conseille cet article détaillé pour surcharger Magento. Dans notre cas, nous n'allons pas surcharger le contrôleur mais une classe. Cependant les principes restent identiques.

class Monprojet_Dataflow_Model_Convert_Adapter_Io extends Mage_Dataflow_Model_Convert_Adapter_Io
{
    public function load()
    {
        parent::load();
        $io = $this->getResource();
        $destDir = $io->pwd() . '/backup/';
        if (false === $io->checkAndCreateFolder($destDir)) {
            $message = Mage::helper('dataflow')->__('Could not create backup folder: "%s".', $destDir);
            Mage::throwException($message);
        }
        return $this;
    }
}

Surcharge de l'adaptateur

Nous avons surchargé la méthode load de la classe Mage_Dataflow_Model_Convert_Adapter_Io. Au moment du chargement du fichier, nous sauvegardons désormais une copie du fichier dans le répertoire backup.
Dans notre exemple, nous ne gardons qu'un seul fichier. Il est tout à fait possible d'imaginer un système d'archivage.

Nouveau parseur

Dans notre exemple, les données à importer sont dans un fichier texte dont les champs sont de largeur fixe. le parseur va donc permettre de transmettre les informations produits en attribut Magento.

class Monprojet_Dataflow_Model_Convert_Parser_Edi_Adonix extends Mage_Dataflow_Model_Convert_Parser_Abstract
class Monprojet_Dataflow_Model_Convert_Parser_Edi_Adonix extends Mage_Dataflow_Model_Convert_Parser_Abstract
{
public function parse()
{
$adapterName = $this->getVar('adapter', null);
$adapterMethod = $this->getVar('method', 'saveRow');
try {
$adapter = Mage::getModel($adapterName);
} catch (Exception $e) {}
        $batchModel = $this->getBatchModel();
$batchIoAdapter = $this->getBatchModel()->getIoAdapter();
$batchIoAdapter->open(false);

        if (is_array($this->getVar('map'))) {
$parseFieldNames = $this->getVar('map');
}
while (($row = $batchIoAdapter->read()) !== false) {
$prevPos = 0;
foreach ($parseFieldNames as $field => $length) {
$itemData[$field] = trim(substr($row, $prevPos, $length));
$prevPos += $length;
}
$this->getBatchImportModel()
->setId(null)
->setBatchId($this->getBatchModel()->getId())
->setBatchData($itemData)
->setStatus(1)
->save();
}

$this->addException(Mage::helper('dataflow')->__('Found %d rows.', $this->_countRows));
$this->addException(Mage::helper('dataflow')->__('Starting %s :: %s', $adapterName, $adapterMethod));

        $batchModel->setParams($this->getVars())
->setAdapter($adapterName)
->save();

        return $this;
}
}

Création du parseur

Le code a été simplifié pour les besoins de notre exemple. Certains tests de validation ont été supprimés. Pour chaque ligne de notre fichier, nous créons un tableau associatif, avec comme clé l'attribut Magento (map), et comme valeur la donnée à insérer. Ce tableau associatif est ensuite transmis à l'adaptateur natif Magento. Ce dernier va créer ou mettre à jour les produits, selon le cas.

Conclusion

Nous avons pu voir succinctement que Magento permettait facilement la prise en charge de nouveaux flux d'imports. Avec ce système, il est très facile d'importer différents types de fichier. Dans notre exemple, il s'agissait d'un fichier dont les champs sont de largeur fixe. Il aurait été possible de réaliser la même chose avec un fichier XML.
En fonctionnement de la volumétrie des données à importer, les temps de traitement peuvent être plus au moins long. Les prochaines versions de Magento devraient améliorer ces processus. A noter, qu'il existe un outil, non officiel, permettant des imports beaucoup plus rapide. Vous pouvez consulter ce billet rédigé sur Magmi.
Si vous avez des remarques, n'hésitez pas.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.