Publié le 21/12/2016 par Simon CARRE
L'ImportBundle peut être utilisé pour importer vos fichiers CSV et transformer chaque ligne du fichier en entité dans Symfony. Il est simple à installer, simple à configurer et surtout extensible.
Vous pourrez facilement ajouter d'autres readers qui vous permettront d'importer des fichiers XML, Excel ou autres.
Lien GitHub :
https://github.com/ClickAndMortar/ImportBundle
Ajoutez le bundle à votre composer.json :
"require": {
...
"clickandmortar/import-bundle": "^1.0"
...
}
Ou plus simplement :
composer require "clickandmortar/import-bundle" "^1.0"
Et enfin chargez le dans votre fichier AppKernel.php :
$bundles = array(
...
new ClickAndMortar\ImportBundle\ClickAndMortarImportBundle(),
);
Vous pouvez mettre en place plusieurs imports pour plusieurs entités directement dans le fichier de configuration de votre projet (config.yml). Voici un exemple de configuration pour l'import d'utilisateurs :
click_and_mortar_import:
entities:
customer_from_pim: # Le nom de votre import
model: Acme\DemoBundle\Entity\Customer
repository: AcmeDemoBundle:Customer
unique_key: id
mappings:
id: "ID"
name: "Name_For_Customer"
firstname: "FirstName"
gender: "Sex"
age: "Age"
Voici une explication sur les différentes options possibles :
Type d'option | Obligatoire | Exemple | Commentaire |
---|---|---|---|
model | Oui | Acme\DemoBundle\Entity\Customer | C'est la classe qui correspond à l'entité que vous souhaitez mapper |
repository | Oui | AcmeDemoBundle:Customer | Le repository de votre entité |
unique_key | Non | id | La clé unique pour l'import (pour éviter les doublons et permettre la mise à jour d'une entité avec plusieurs imports successifs) |
only_update | Non | false | true: Mettre à jour les entités uniquement / false: Créer et mettre à jour |
import_helper_service | Non | acme.demo.import_helper.my_import_helper | Vous pouvez ajouter ici l'identifiant d'un service pour étendre votre import et modifier les propriétés de votre entité avant l'enregistrement (nous allons voir celà juste en dessous) |
Un import simple des données c'est bien, mais on peut avoir besoin parfois d'effectuer des opérations sur les données avant de les enregistrer dans la base de données ou de créer de nouvelles propriétés en fonction d'autres. L'option import_helper_service vous permet de faire tout ça.
Commencez par créer un dossier ImportHelper dans votre bundle custom et créez le service suivant :
<?php
namespace MyProject\MyCustomImportBundle\ImportHelper;
use ClickAndMortar\ImportBundle\ImportHelper\ImportHelperInterface;
use MyProject\MyCustomImportBundle\Entity\Customer;
/**
* Class MyImportHelper
*
* @package MyProject\MyCustomImportBundle\MyImportHelper
*/
class MyImportHelper implements ImportHelperInterface
{
/**
* Complete your $entity with $data from import
*
* @param Customer $entity
* @param array $data
* @param array $errors
*/
public function completeData(&$entity, array $data, array &$errors)
{
// Call all necessary methods here to update your $entity
}
}
Et déclarez le service dans votre fichier services.yml :
parameters:
# Import helpers
myproject.import_helpers.my_custom_import_helper.class: MyProject\MyCustomImportBundle\ImportHelper\MyImportHelper
services:
# Import helpers
myproject.import_helpers.my_custom_import_helper:
class: %myproject.import_helpers.my_custom_import_helper.class%
La méthode completeData sera appelée après le mapping classique pour mettre à jour d'autres propriétés sur votre entité via le tableau des données $data. Si une erreur a lieu, vous pouvez la stocker dans le tableau $errors, elle remontera à la fin de l'import.
Pas de soucis, il faut ajouter un reader qui correspond à vos besoins (n'hésitez d'ailleurs pas à nous soumettre vos propres readers pour qu'on les intégrer dans le projet). Ajoutez une classe MyCustomXmlReader.php dans le dossier Reader/Readers de votre bundle :
<?php
namespace MyBundle\MyCustomImportBundle\Reader\Readers;
use ClickAndMortar\ImportBundle\Reader\AbstractReader;
/**
* Class MyCustomXmlReader
*
* @package MyBundle\MyCustomImportBundle\Reader\Readers
*/
class MyCustomXmlReader extends AbstractReader
{
/**
* Read my custom XML file and return data array
*
* @param string $path
*
* @return array
*/
public function read($path)
{
$data = array();
...
return $data;
}
/**
* Support only xml type
*
* @param string $type
*
* @return bool
*/
public function support($type)
{
return $type == 'xml';
}
}
Et ajoutez ce reader avec le bon tag dans votre fichier services.yml :
parameters:
myproject.my_custom_import_bundle.reader.my_custom_xml_reader.class: MyBundle\MyCustomImportBundle\Reader\Readers\MyCustomXmlReader
services:
myproject.my_custom_import_bundle.reader.my_custom_xml_reader:
class: %myproject.my_custom_import_bundle.reader.my_custom_xml_reader.class%
tags:
- { name: clickandmortar.import.reader }
Le but est ensuite d'alimenter le tableau $data dans la méthode read via la lecture de votre fichier XML.
Et le moment de l'utilisation est enfin arrivé ! Et bien l'import se fait ensuite simplement via la ligne de commande suivante :
php app/console candm:import /path/of/your/file/customers.csv customer_from_pim --delete-after-import
L'option --delete-after-import est facultative, elle vous permet de supprimer le fichier du dossier après l'import. Ajoutez la ligne dans votre crontab et vous avez un système automatisé d'import complet sur Symfony !