Paul
 Le Flem

Faciliter l'ajout de produits en important depuis excel

Dans cet article, j'explique ma méthodologie lorsque j'ai besoin d'importer un grand nombre de produit depuis un fichier excel vers un site e-commerce.

Bien que l'exemple utilise des produits, il est également possible de l'utiliser pour importer tout type de données, que ce soit des utilisateurs, des produits, des articles de blog etc...

Dernier point : j'utilise dans le cadre de cet article le framework Symfony. Bien que cela oriente légérement le code, il est tout à fait possible d'utiliser un autre framework, ou simplement PHP "pure".

PhpSpreadSheet

Pour importer nos produits, nous allons utiliser la librairie PHPOffice / PhpSpreadsheet.

Commençont par l'installer en utilisant Composer :

composer require phpoffice/phpspreadsheet

Si vous n'avez pas composer installé, vous pouvez l'installer ici, ou installer la librairie manuellement depuis leur GitHub

Utiliser la librairie

Tous d'abord, il est nécessaire d'instancier un Reader : c'est la classe qui permet la lecture du fichier. Il existe plusieurs readers, adapté à chaque version de fichier (.csv, .xlsx...). Dans mon cas, ce sera Xlsx, mais cela n'as pas d'impact sur la suite, car ils fonctionnent tous de la même manière.

$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx()

La première étape pour importer les données sera de charger le fichier. Pour cela, nous utiliserons l'instruction suivante :

$spreadSheet = $reader->load($file);

Ensuite, il faudra sélectionner la feuille à utiliser. Si votre fichier n'en contient qu'une, vous pouvez utiliser l'instruction suivante :

$sheet = $spreadSheet->getActiveSheet();

Sinon, vous pouvez utiliser la méthode suivante pour sélectionner une feuille en fonction de son nom :

$sheet = $spreadSheet->getSheetByName("nom-de-ma-feuille");

Nous utiliserons ensuite la méthode $sheet->getCell("identifiant_cellule") pour sélectionner une cellule, puis la méthode GetValue() nous permettra de récupérer sa valeur.

Déterminer la méthode à utiliser

Maintenant que vous avez accès au fichier, il va falloir boucler dessus pour en lire les données.

Avant tout, il est nécessaire de déterminer comment procéder : il faut alors analyser le fichier que vous aller utiliser pour choisir la bonne méthode d'import.

Selon le cas, il faudra agir différement. Si votre fichier n'est pas "nettoyé", vous avez deux options : nettoyer le fichier au préalable manuellement, ce qui peut être très long dépendant de la taille du fichier. Vous pouvez également prendre en compte dans votre code que certaines valeurs ne sont pas correct : ignorer les valeurs nulles, ou les lignes incomplètes

Exemple avec un fichier propre

Pour cet exemple, nous utiliserons la structure suivante pour le fichier excel, et considererons qu'il est déja "propre".

Nom du produit Description Prix
Table basse Table basse en bois d'acajou. Dimensions 150cm x 70cm 145
Luminaire Luminaire sur pieds. Dimensions 185cm x 45cm 89
Chaise de jardin Chaise de jardin en plastique 24

$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
$spreadSheet = $reader->load($file);
$sheet = $spreadSheet->getActiveSheet();

// Permet d'itérer sur les lignes du fichier
$rows = $sheet->getRowIterator();

// Récupère l'EntityManager (remplacer par PDO si vous n'utilisez pas Doctrine)
$em = $doctrine->getManager();

$i = 0;

foreach($rows as $row) {
	// On ignore la première ligne car elle contient les titres. Si vous n'avez pas les titres dans votre fichier, vous pouvez ignorer cette ligne.
	if ($i === 0) {
		$i++;
		continue;
	}

	$product = new Product();

	// Le nom du produit se situe sur la première colonne du fichier
	$product->setName($sheet->getCell("A1")->getValue());

	$product->setDescription($sheet->getCell("B1")->getValue());

	// Il est nécessaire de cast la valeur car un string est retourné
	$product->setPrice((int) $sheet->getCell("C1")->getValue());

	// Enregistre la requête (remplacer par PDO si vous n'utilisez pas Doctrine)
	$em->persist($product);
}

// Envoie les requêtes à la base de données (remplacer par PDO si vous n'utilisez pas Doctrine)
$em->flush();
		

Exemple avec un fichier "sale"

Pour cet exemple, imaginons un fichier incomplet.

Nom du produit Description Prix
Table basse 145
Luminaire Luminaire sur pieds. Dimensions 185cm x 45cm
Chaise de jardin Chaise de jardin en plastique 24

$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
$spreadSheet = $reader->load($file);
$sheet = $spreadSheet->getActiveSheet();

// Permet d'itérer sur les lignes du fichier
$rows = $sheet->getRowIterator();

// Récupère l'EntityManager (remplacer par PDO si vous n'utilisez pas Doctrine)
$em = $doctrine->getManager();

$i = 0;

foreach($rows as $row) {
	// On ignore la première ligne car elle contient les titres. Si vous n'avez pas les titres dans votre fichier, vous pouvez ignorer cette ligne.
	if ($i === 0) {
		$i++;
		continue;
	}

	$product = new Product();

	// Si pas de nom de produit ou de prix, on ignore la ligne
	if ($sheet->getCell("A$i)->getValue() == null || $sheet->getCell("C$i)->getValue()) {
		continue;
	}

	// Le nom du produit se situe sur la première colonne du fichier
	$product->setName($sheet->getCell("A1")->getValue());

	// On accepte qu'il n'y ait pas de description, mais on la remplace par le titre si elle n'existe pas
	$product->setDescription($sheet->getCell("B1")->getValue() ? $sheet->getCell("B1")->getValue() : $sheet->getCell("A1")->getValue());

	// Il est nécessaire de cast la valeur car un string est retourné
	$product->setPrice((int) $sheet->getCell("C1")->getValue());

	// Enregistre la requête (remplacer par PDO si vous n'utilisez pas Doctrine)
	$em->persist($product);
}

// Envoie les requêtes à la base de données (remplacer par PDO si vous n'utilisez pas Doctrine)
$em->flush();
		

Et voilà, c'est déja finit ! Si vous avez des questions, n'hésitez pas à me contacter par email: contact@paul-le-flem.fr