Les importations massives en PHP commencent souvent par un CSV envoyé par un client, un export d'un fournisseur ou une extraction d'un système hérité. Le risque apparaît lorsqu'elles sont traitées comme une simple lecture de fichier suivie d'insertions en base de données. Une ligne peut avoir un format valide et, malgré cela, créer un doublon, enfreindre une règle métier, écraser des informations en vigueur ou déclencher deux fois un effet externe.
Une importation doit être conçue comme un processus opérationnel avec un cycle défini : réception, analyse, validation, prévisualisation, confirmation, exécution, revue et récupération. Cette approche permet à l'équipe produit de comprendre ce qui sera intégré, aux opérations d'intervenir face aux exceptions et à la technologie de limiter l'impact des données défectueuses.
Traiter l'importation comme un processus métier

Le fichier n'est pas à lui seul la source de vérité : il s'agit d'une demande de modification de l'état de l'application. Il convient donc de créer une entité d'importation avec son propre identifiant, l'utilisateur ou le système qui l'a initiée, la date de réception, le type de données, la version du contrat, le fichier ou une référence sécurisée vers celui-ci, l'état global et un résumé des résultats.
Les états globaux doivent exprimer une situation exploitable, et pas seulement un booléen. Par exemple : reçu, analysé, en attente de confirmation, en cours, terminé, terminé avec incidents, arrêté ou annulé. Une importation avec 9 800 lignes acceptées et 200 rejetées n'est pas nécessairement un échec ; elle peut être une exécution terminée avec incidents si les lignes rejetées sont isolées et expliquées.
Il faut aussi décider quelles conséquences relèvent du chargement. Créer une commande, mettre à jour un catalogue ou créer des contacts peut nécessiter des calculs, une piste d'audit ou des notifications. Séparer la persistance principale des effets secondaires réduit le risque qu'une nouvelle tentative envoie des messages répétés ou exécute des intégrations de manière non contrôlée.
Définir un contrat d'entrée avant d'accepter des fichiers
Le contrat d'importation précise ce qui doit être reçu et comment cela sera interprété. Il doit inclure le format autorisé, l'encodage, le séparateur, les en-têtes, les types de données, les champs obligatoires, le format des dates, les règles de normalisation, les limites de taille et le nombre maximal de lignes. Si des feuilles de calcul sont acceptées, il faut également définir la feuille pertinente et la manière dont seront traitées les cellules vides, les formules et les valeurs converties automatiquement.
Les champs qui relient l'origine à la destination méritent une attention particulière. Un identifiant externe stable, tel que le code client dans le système source, est préférable à l'utilisation du numéro de ligne ou d'un nom comme référence. Il faut préciser si cet identifiant crée un enregistrement, met à jour un enregistrement existant ou si les deux opérations sont autorisées.
Séparer les couches de validation
La validation structurelle répond à des questions mécaniques : le fichier peut-il être lu ?, les colonnes requises existent-elles ?, la date a-t-elle un format autorisé ?, le montant est-il numérique ?, la ligne respecte-t-elle la limite de longueur ? Cette couche doit détecter tôt les problèmes qui empêchent d'interpréter les données.
La validation de domaine applique les règles métier : un état peut ne pas être autorisé, une date de fin ne peut pas précéder la date de début, un pourcentage doit rester dans sa plage ou une combinaison de champs peut être incompatible. Enfin, les vérifications par rapport aux données existantes contrôlent les références, les autorisations, l'unicité et les transitions autorisées. Par exemple, qu'un code fournisseur existe, que l'utilisateur puisse intervenir sur cette organisation ou qu'un enregistrement ne soit pas verrouillé.
Cette séparation améliore les messages et le diagnostic. Il n'est pas équivalent de signaler une colonne absente, une référence inexistante ou une modification non autorisée. En outre, les règles de domaine doivent être réutilisées depuis l'application et depuis l'importateur afin d'éviter que le chargement ne devienne un raccourci contournant les contrôles habituels.
Prévisualiser les modifications et confirmer une intention explicite
La prévisualisation ne doit pas promettre une exécution exacte si les données peuvent changer entre l'analyse et la confirmation, mais elle doit fournir une estimation vérifiable. Affichez le total des lignes lues, les lignes valides, les lignes avec avertissements, les lignes rejetées, les créations prévues, les mises à jour prévues et les enregistrements qui ne subiront aucune modification.
Les avertissements servent aux cas qui nécessitent une attention, mais n'invalident pas automatiquement une ligne : par exemple, un téléphone normalisé, une description tronquée selon une règle connue ou un champ facultatif vide. Les avertissements ne doivent pas masquer les rejets. Chaque résultat nécessite un code stable, un message compréhensible et, lorsque cela est sûr, la valeur reçue et la valeur normalisée.
La confirmation doit être associée à une version précise de l'analyse. Si l'utilisateur remplace le fichier, corrige des lignes dans une interface ou modifie des paramètres pertinents, le système doit invalider la prévisualisation précédente et exiger une nouvelle analyse. Cela évite de confirmer un résumé qui ne représente plus le chargement réel.
Traiter par lots sans états ambigus
Traiter toutes les lignes dans une seule transaction semble sûr, mais peut maintenir des verrous trop longtemps, dépasser les limites d'exécution ou transformer une défaillance ponctuelle en un rollback coûteux. Traiter une ligne par transaction peut, à l'inverse, générer trop de surcharge et rendre difficile la coordination d'opérations liées.
L'unité de travail doit être choisie selon la dépendance entre les enregistrements, le volume et le coût d'un rollback. Dans de nombreux cas, un petit lot délimité permet de valider les modifications progressivement. Chaque lot doit enregistrer son début, sa fin, le nombre de lignes traitées et le résultat. Le worker doit pouvoir reprendre sans dépendre d'une session HTTP ouverte : le chargement est confirmé depuis l'interface, mais son exécution est réalisée comme tâche en arrière-plan.
Évitez de conserver des fichiers entiers en mémoire. Lisez de manière séquentielle, normalisez chaque ligne et stockez une représentation de travail ou un résultat de validation lorsque cela est nécessaire pour auditer et reprendre. Imposez des limites de taille, de lignes, de temps et de concurrence. Un fichier anormalement volumineux ne doit pas bloquer les ressources qui assurent le travail quotidien.
pour chaque lot en attente :
marquer le lot comme en_cours
pour chaque ligne du lot :
appliquer les validations en attente
persister ou envoyer en quarantaine
enregistrer le résultat par ligne
valider le lot
marquer le lot comme terminéSi un worker est interrompu, il ne suffit pas de réexécuter le lot aveuglément. Un mécanisme de verrouillage avec expiration ou récupération est nécessaire, et l'état par ligne doit permettre de distinguer ce qui est en attente de ce qui est déjà validé.
Isoler les erreurs en quarantaine et conserver les preuves
La quarantaine permet que les lignes invalides ne bloquent pas les lignes correctes sans disparaître du processus. Une ligne en quarantaine doit conserver le numéro ou l'identifiant d'origine, les données reçues sous contrôles d'accès, les données normalisées si elles existent, les codes d'erreur, le moment de détection et l'état d'examen.
Toutes les erreurs ne reçoivent pas le même traitement. Un fichier sans en-tête requis est une erreur de fichier et peut arrêter l'analyse complète. Une référence à un fournisseur inexistant peut être un rejet de ligne. Une indisponibilité temporaire de la base de données ou d'une intégration est une erreur technique réessayable et ne doit pas être étiquetée comme un défaut de donnée.
L'interface opérationnelle doit permettre de filtrer par motif, d'exporter uniquement les incidents autorisés et de comprendre quelle correction est attendue. Corriger dans l'application peut être utile pour peu de cas ; pour de nombreux enregistrements, il est généralement plus contrôlable de télécharger les incidents, de les corriger à la source et de présenter un nouveau chargement. Dans les deux cas, conservez l'historique : modifier une ligne en quarantaine ne doit pas effacer la valeur d'origine ni le motif initial.
Garantir l'idempotence et éviter les doublons
L'idempotence signifie que répéter une opération avec la même intention ne modifie pas le résultat plus d'une fois. Elle est essentielle, car les nouvelles tentatives surviennent : un délai d'attente expire, un processus redémarre ou un opérateur confirme à nouveau face à une réponse incertaine.
Une clé d'idempotence peut être construite à partir du type d'importation, de l'organisation de destination et d'un identifiant externe stable. Elle doit être soutenue par des contraintes d'unicité dans la base de données lorsque le modèle le permet ; vérifier d'abord puis insérer n'élimine pas les conditions de concurrence entre workers simultanés.
Pour les mises à jour, définissez une politique explicite : remplacer des champs, appliquer uniquement les valeurs non vides, rejeter les conflits ou exiger une version attendue de l'enregistrement. La dernière option aide à détecter qu'un utilisateur a modifié la donnée après la prévisualisation. N'utilisez pas une empreinte du fichier comme unique mécanisme : un même contenu peut représenter une intention différente et un fichier corrigé peut conserver de nombreuses lignes déjà traitées.
Traçabilité, nouvelles tentatives et récupération sélective

Le résultat par ligne est l'élément central pour le support et la récupération. Enregistrez un état tel que en attente, traitée, rejetée, en quarantaine, nouvelle tentative en attente ou ignorée ; l'identifiant externe ; le lot ; les codes de motif ; les horodatages ; et une référence à l'enregistrement créé ou mis à jour. Protégez les données personnelles et les secrets : la traçabilité doit être suffisante pour enquêter, et non une copie indiscriminée d'informations sensibles dans les logs.
Les nouvelles tentatives doivent être sélectives. Réessayez automatiquement les erreurs techniques transitoires avec des limites et une attente progressive ; ne réessayez pas indéfiniment une règle de domaine non respectée. Lorsqu'une référence manquante ou une donnée invalide est corrigée, retraitez uniquement les lignes en quarantaine concernées. Lorsqu'un lot échoue, poursuivez à partir des lignes en attente et utilisez celles déjà traitées comme preuve d'avancement.
Avant de mettre le flux en production, testez les fichiers vides, les en-têtes modifiés, les encodages inattendus, les doublons au sein du même fichier, les doublons par rapport à la base de données, les interruptions entre les lots, les reprises et les autorisations insuffisantes. Les importations massives en PHP sont fiables lorsque leur comportement face à une défaillance est conçu avec la même précision que leur chemin nominal.



