yoanbernabeu / edilabo-bundle
A Symfony bundle to parse/export Edilabo XML files.
Installs: 91
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/yoanbernabeu/edilabo-bundle
Requires
- symfony/config: ^7.3
- symfony/dependency-injection: ^7.3
- symfony/http-kernel: ^7.3
- symfony/serializer-pack: ^1.3
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.64
- phpstan/phpstan: ^1.12
- phpstan/phpstan-beberlei-assert: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.2
- phpstan/phpstan-phpunit: ^1.4
- phpstan/phpstan-strict-rules: ^1.6
- phpunit/phpunit: ^11.3
- symfony/phpunit-bridge: ^7.3
README
Un bundle Symfony pour importer et exporter les fichiers XML EDILABO (format SANDRE) utilisés pour les échanges entre laboratoires et commanditaires dans le domaine de l'environnement.
📋 Description
Ce bundle permet de parser et générer des fichiers XML conformes au scénario d'échange SANDRE COM_LABO version 1.1, utilisé pour les demandes de prestations (prélèvements et analyses) entre commanditaires et laboratoires.
Le bundle couvre 100% du format SANDRE COM_LABO v1.1, incluant tous les champs optionnels et obligatoires définis dans la spécification.
Fonctionnalités
- ✅ Import XML : Parser des fichiers XML EDILABO vers des objets PHP
- ✅ Export XML : Générer des fichiers XML EDILABO à partir d'objets PHP
- ✅ Validation XML : Validation basique et stricte (XSD) des fichiers
- ✅ Couverture complète : Tous les éléments du format SANDRE COM_LABO v1.1
- ✅ Type-safety : 11 Enums PHP pour 314 valeurs de nomenclatures SANDRE
Warning
Ce bundle est en cours de développement actif :
- ❌ Aucune garantie de rétrocompatibilité entre les versions
- ⚠️ L'API peut changer radicalement sans préavis
- 💥 Des breaking changes sont attendus dans les futures versions
N'utilisez pas en production avant la sortie d'une version stable.
🚀 Installation
composer require yoanbernabeu/edilabo-bundle
📖 Utilisation
Configuration dans Symfony
Le bundle s'enregistre automatiquement dans votre application Symfony. Le service principal EdilaboInterface
est disponible via l'injection de dépendances.
Exemples d'utilisation
Injection dans un contrôleur
<?php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use YoanBernabeu\EdilaboBundle\EdilaboInterface; class LabController extends AbstractController { public function __construct( private readonly EdilaboInterface $edilabo ) { } public function parse(): Response { // Parser un fichier $comLabo = $this->edilabo->parseFile('/path/to/commande.xml'); // Accéder aux données $scenario = $comLabo->getScenario(); $codeScenario = $scenario->getCodeScenario(); // "COM_LABO" $version = $scenario->getVersionScenario(); // "1" // Accéder aux intervenants foreach ($comLabo->getIntervenants() as $intervenant) { $nom = $intervenant->getNomIntervenant(); $code = $intervenant->getCdIntervenant(); } // Accéder aux demandes foreach ($comLabo->getDemandes() as $demande) { $reference = $demande->getCdDemandeCommanditaire(); // Les champs nomenclature SANDRE sont des Enums type-safe $typeDemande = $demande->getTypeDemande(); // TypeDemande Enum $contexte = $demande->getContexteCodification(); // ContexteCodification Enum // Une demande peut avoir plusieurs prélèvements foreach ($demande->getPrelevements() as $prelevement) { $datePrel = $prelevement->getDatePrel(); $support = $prelevement->getSupport(); // Les finalités sont des Enums foreach ($prelevement->getFinalitesPrel() as $finalite) { $code = $finalite->getCode(); // '1', '2', 'AS', 'CS', etc. $libelle = $finalite->getLibelle(); // 'Demande de prélèvement(s)', etc. } foreach ($prelevement->getEchantillons() as $echantillon) { $ref = $echantillon->getRefEchantillonCommanditaire(); } } } return new Response('Parsing terminé'); } }
Parser depuis une chaîne XML
use YoanBernabeu\EdilaboBundle\EdilaboInterface; $xmlContent = file_get_contents('/path/to/file.xml'); $comLabo = $edilabo->parse($xmlContent);
Parser depuis un fichier
use YoanBernabeu\EdilaboBundle\EdilaboInterface; $comLabo = $edilabo->parseFile('/path/to/commande.xml');
Valider un XML
use YoanBernabeu\EdilaboBundle\EdilaboInterface; use YoanBernabeu\EdilaboBundle\Exception\E1_MalformedXmlException; use YoanBernabeu\EdilaboBundle\Exception\E2_SchemaValidationException; try { $isValid = $edilabo->validate($xmlContent); echo "XML valide !"; } catch (E1_MalformedXmlException $e) { echo "[E1] XML mal formaté : " . $e->getMessage(); } catch (E2_SchemaValidationException $e) { echo "[E2] Structure invalide : " . $e->getMessage(); }
Exporter vers XML
Le bundle permet également de créer et exporter des fichiers XML EDILABO à partir d'objets PHP.
Export vers une chaîne XML :
use YoanBernabeu\EdilaboBundle\Builder\ComLaboBuilder; use YoanBernabeu\EdilaboBundle\Builder\ScenarioBuilder; use YoanBernabeu\EdilaboBundle\Model\Emetteur; use YoanBernabeu\EdilaboBundle\Model\Destinataire; // Créer un ComLabo avec les builders fluides $emetteur = new Emetteur( cdIntervenant: '12345678900001', nomIntervenant: 'Mon Entreprise', service: null, contact: null ); $destinataire = new Destinataire( cdIntervenant: '98765432100002', nomIntervenant: 'Laboratoire XYZ', service: null, contact: null ); $scenario = ScenarioBuilder::create() ->setReferenceFichierEnvoi('CMD_2025_001.xml') ->setDateCreationFichier('2025-01-15') ->setEmetteur($emetteur) ->setDestinataire($destinataire) ->build(); $comLabo = ComLaboBuilder::create() ->setScenario($scenario) ->build(); // Export vers XML $xml = $edilabo->export($comLabo);
Export vers un fichier :
$edilabo->exportToFile($comLabo, '/path/to/export.xml');
Exemple complet avec demande et prélèvement :
use YoanBernabeu\EdilaboBundle\Builder\DemandeBuilder; use YoanBernabeu\EdilaboBundle\Builder\PrelevementBuilder; use YoanBernabeu\EdilaboBundle\Model\Commanditaire; use YoanBernabeu\EdilaboBundle\Model\Prestataire; use YoanBernabeu\EdilaboBundle\Model\Echantillon; use YoanBernabeu\EdilaboBundle\Model\GroupeParametresRef; use YoanBernabeu\EdilaboBundle\Model\Laboratoire; use YoanBernabeu\EdilaboBundle\Model\StationPrelevementRef; use YoanBernabeu\EdilaboBundle\Model\Support; use YoanBernabeu\EdilaboBundle\Model\Preleveur; use YoanBernabeu\EdilaboBundle\Model\Enum\ContexteCodification; use YoanBernabeu\EdilaboBundle\Model\Enum\TypeDemande; use YoanBernabeu\EdilaboBundle\Model\Enum\FinalitePrelevement; use YoanBernabeu\EdilaboBundle\Model\Enum\NatureProduit; use YoanBernabeu\EdilaboBundle\Model\Enum\UsageProduit; // Créer un échantillon $echantillon = new Echantillon( refEchantillonCommanditaire: 'ECH_2025_001', refEchantillonPrel: null, refEchantillonLabo: null, groupesParametres: [new GroupeParametresRef('GP_SOL')], laboratoire: new Laboratoire('98765432100002'), payeur: null, methodeTransport: null, analyses: [], commemoratifs: [] ); // Créer un prélèvement avec le builder et des Enums type-safe $prelevement = PrelevementBuilder::create() ->setCdPrelevement('PREL_2025_001') ->setDatePrel('2025-01-10') ->setDelaiPrel('5') ->setStationPrelevement(new StationPrelevementRef('STATION_001')) ->setSupport(new Support('25', 'Sol')) ->setPreleveur(new Preleveur('11122233344455')) ->addFinalitePrel(FinalitePrelevement::CONTROLE_SANITAIRE_REGLEMENTAIRE) ->setNatureProduit(NatureProduit::EAU_SURFACE) ->setUsageProduit(UsageProduit::CONSOMMATION_HUMAINE) ->addEchantillon($echantillon) ->build(); // Créer une demande avec le builder et des Enums type-safe $demande = DemandeBuilder::create() ->setCdDemandeCommanditaire('CMD_2025_001') ->setCommanditaire(new Commanditaire('12345678900001')) ->setPrestataire(new Prestataire('98765432100002')) ->setTypeDemande(TypeDemande::ANALYSE) ->setContexteCodification(ContexteCodification::DEMANDE_ET_RESULTATS) ->setReferenceMarche('MARCHE_2025') ->setCommentairesCommanditaire('Analyse de sol') ->addPrelevement($prelevement) ->build(); // Construire le ComLabo complet $comLabo = ComLaboBuilder::create() ->setScenario($scenario) ->addDemande($demande) ->build(); // Export $xml = $edilabo->export($comLabo);
Validation XSD stricte
Le bundle permet également de valider les fichiers XML contre le schéma XSD officiel SANDRE. Cette validation est beaucoup plus stricte que la validation basique :
use YoanBernabeu\EdilaboBundle\EdilaboInterface; use YoanBernabeu\EdilaboBundle\Exception\E1_MalformedXmlException; use YoanBernabeu\EdilaboBundle\Exception\E2_SchemaValidationException; use YoanBernabeu\EdilaboBundle\Validator\XsdValidator; try { // Validation avec le schéma XSD officiel SANDRE (connexion internet requise) $edilabo->validateWithXsd($xmlContent); echo "XML conforme au schéma SANDRE !"; } catch (E1_MalformedXmlException $e) { echo "[E1] XML mal formaté : " . $e->getMessage(); } catch (E2_SchemaValidationException $e) { // Affiche les erreurs de conformité détaillées echo "[E2] XML non conforme au schéma : " . $e->getMessage(); }
Vous pouvez également spécifier un chemin de schéma personnalisé :
// Utiliser le schéma officiel SANDRE (par défaut - constante) $edilabo->validateWithXsd($xmlContent); // Équivalent à : $edilabo->validateWithXsd($xmlContent, XsdValidator::SANDRE_SCHEMA_URL); // Utiliser un schéma local personnalisé $edilabo->validateWithXsd($xmlContent, '/path/to/schema.xsd');
⚠️ Performance : La validation XSD est stricte mais lente (~50s par fichier car elle télécharge le schéma distant et résout les imports). Utilisez-la uniquement pour des cas où la validation basique
validate()
ne suffit pas (doute sur la conformité du XML...).
🎯 Enums de nomenclature SANDRE
Le bundle fournit 11 Enums PHP couvrant 314 valeurs des nomenclatures SANDRE pour garantir la sécurité des types et faciliter le développement avec autocomplétion IDE.
Enums disponibles
Enum | Valeurs | Utilisation |
---|---|---|
ContexteCodification |
2 | Contexte d'échange EDILABO |
TypeDemande |
3 | Type de demande (prélèvement, analyse, mixte) |
FinalitePrelevement |
37 | Finalité du prélèvement (contrôle sanitaire, auto-surveillance, etc.) |
NatureProduit |
123 | Nature du produit prélevé (eaux, boues, effluents agricoles, composts, engrais) |
UsageProduit |
7 | Usage du produit (thermalisme, baignade, consommation, etc.) |
ZoneVerticaleProspectee |
16 | Zone verticale du plan d'eau (thermocline, hypolimnion, etc.) |
OrigineCodeStation |
11 | Origine du code de la station de prélèvement |
OrigineCodeLocal |
11 | Origine du code du local de prélèvement |
SystemeProjection |
68 | Système de projection géographique (Lambert, etc.) |
SystemeAltimetrique |
33 | Système altimétrique (NGF, IGN, etc.) |
LocalisationAnalyse |
3 | Localisation de l'analyse (in situ, laboratoire) |
Utilisation des Enums
use YoanBernabeu\EdilaboBundle\Model\Enum\TypeDemande; use YoanBernabeu\EdilaboBundle\Model\Enum\FinalitePrelevement; use YoanBernabeu\EdilaboBundle\Model\Enum\NatureProduit; // Créer une demande avec type-safety $demande = DemandeBuilder::create() ->setTypeDemande(TypeDemande::ANALYSE) // Enum au lieu de string ->build(); // Accéder aux valeurs de l'Enum $typeDemande = $demande->getTypeDemande(); echo $typeDemande->getCode(); // '2' echo $typeDemande->getLibelle(); // 'Demande d\'analyse(s)' // Créer un prélèvement avec des Enums $prelevement = PrelevementBuilder::create() ->addFinalitePrel(FinalitePrelevement::CONTROLE_SANITAIRE_REGLEMENTAIRE) ->setNatureProduit(NatureProduit::EAU_SURFACE) ->build(); // Accéder aux finalités (array d'Enums) foreach ($prelevement->getFinalitesPrel() as $finalite) { echo $finalite->getMnemonique(); // 'CS' echo $finalite->getLibelle(); // 'Contrôle sanitaire réglementaire' echo $finalite->getCode(); // 'CS' } // Parser depuis XML : les valeurs sont automatiquement converties en Enums $comLabo = $edilabo->parseFile('commande.xml'); $demande = $comLabo->getDemandes()[0]; $type = $demande->getTypeDemande(); // TypeDemande Enum, pas string
Avantages des Enums
- ✅ Type-safety : Impossible d'assigner une valeur invalide
- ✅ Autocomplétion IDE : Toutes les valeurs possibles sont suggérées
- ✅ Documentation : Libellés et mnémoniques disponibles via méthodes
- ✅ Validation : Erreur à la compilation si valeur incorrecte
- ✅ Refactoring : Renommage sûr dans toute la codebase
🏗️ Structure des objets
ComLabo (racine)
L'objet principal qui contient toutes les données du fichier EDILABO.
$comLabo->getScenario(); // Scenario $comLabo->getIntervenants(); // Intervenant[] $comLabo->getStationsPrelevement(); // StationPrelevement[] $comLabo->getGroupesParametres(); // GroupeParametres[] $comLabo->getDemandes(); // Demande[]
Scenario
Informations sur le scénario d'échange.
$scenario->getCodeScenario(); // "COM_LABO" $scenario->getVersionScenario(); // "1" $scenario->getNomScenario(); // Nom du scénario $scenario->getDateCreationFichier(); // Date de création $scenario->getReferenceFichierEnvoi(); // Référence du fichier $scenario->getEmetteur(); // Emetteur (avec Service et Contact) $scenario->getDestinataire(); // Destinataire (avec Service et Contact) $scenario->getReferentiels(); // Referentiel[] - Référentiels SANDRE utilisés
Intervenant
Représente un acteur (commanditaire, prestataire, laboratoire).
$intervenant->getCdIntervenant(); // Code SIRET $intervenant->getNomIntervenant(); // Nom de l'intervenant $intervenant->getMnIntervenant(); // Mention $intervenant->getRueIntervenant(); // Rue $intervenant->getVilleIntervenant(); // Ville $intervenant->getCPIntervenant(); // Code postal // ... et autres champs d'adresse (BP, Immeuble, Lieu-dit, Département)
StationPrelevement
Informations sur le lieu de prélèvement.
$station->getCdStationPrelevement(); // Code de la station $station->getLbStationPrelevement(); // Libellé $station->getOrigineCode(); // OrigineCodeStation Enum $station->getTypeStationPrelevement(); // Type $station->getAdresseStationPrelevement(); // Adresse $station->getZoneVerticaleProspectee(); // ZoneVerticaleProspectee Enum (16 valeurs) $station->getCoordXStationPrelevement(); // Coordonnée X $station->getCoordYStationPrelevement(); // Coordonnée Y $station->getProjectStationPrelevement(); // Projection $station->getAltitudeStationPrelevement(); // SystemeProjection Enum (68 valeurs) $station->getProjectAltiStationPrelevement(); // SystemeAltimetrique Enum (33 valeurs) $station->getCommune(); // Commune $station->getLocauxPrelevement(); // LocalPrelevement[] - Locaux détaillés
GroupeParametres
Ensemble d'analyses regroupées.
$groupe->getCdGroupeParametres(); // Code du groupe $groupe->getLbGroupeParametres(); // Libellé $groupe->getAnalyses(); // Analyse[]
Analyse
Détails d'une analyse de laboratoire.
$analyse->getInsituAna(); // LocalisationAnalyse Enum (IN_SITU, LABORATOIRE) $analyse->getParametre(); // Parametre $analyse->getFractionAnalysee(); // FractionAnalysee $analyse->getUniteReference(); // UniteReference $analyse->getMethode(); // Methode (optionnel) $analyse->getCommentairesAna(); // Commentaires $analyse->getMethFractionnement(); // Méthode de fractionnement $analyse->getMethExtraction(); // Méthode d'extraction $analyse->getSolvant(); // Solvant utilisé $analyse->getPayeur(); // Payeur de l'analyse $analyse->getCommemoratifs(); // Commemoratif[]
Demande
Une demande de prestations.
$demande->getCdDemandeCommanditaire(); // Code de la demande $demande->getCommanditaire(); // Commanditaire $demande->getPrestataire(); // Prestataire $demande->getTypeDemande(); // TypeDemande Enum (PRELEVEMENT, ANALYSE, MIXTE) $demande->getContexteCodification(); // ContexteCodification Enum $demande->getCdDemandePrestataire(); // Code demande prestataire $demande->getDateDemande(); // Date de la demande $demande->getLbDemande(); // Libellé $demande->getDateDebutApplicationDemande(); // Date début application $demande->getDateFinApplicationDemande(); // Date fin application $demande->getReferenceMarche(); // Référence marché $demande->getPayeur(); // Payeur $demande->getDestinatairesRsAna(); // DestinataireRsAna[] - Destinataires des résultats $demande->getPrelevements(); // Prelevement[] - Prélèvements $demande->getCommemoratifs(); // Commemoratif[]
Prelevement
Informations sur un prélèvement.
$prelevement->getCdPrelevement(); // Code du prélèvement $prelevement->getDatePrel(); // Date du prélèvement $prelevement->getHeurePrel(); // Heure du prélèvement $prelevement->getDelaiPrel(); // Délai de prélèvement $prelevement->getDureePrel(); // Durée du prélèvement $prelevement->getReferencePrel(); // Référence $prelevement->getFinalitesPrel(); // FinalitePrelevement[] - Finalités (Enums) $prelevement->getCommentairesPrel(); // Commentaires $prelevement->getRisqueProduit(); // Risque produit $prelevement->getStationPrelevement(); // StationPrelevementRef $prelevement->getLocalPrelevement(); // LocalPrelevementRef $prelevement->getLocalExactePrel(); // Localisation exacte $prelevement->getSupport(); // Support (Sol, Eau, etc.) $prelevement->getMethodePrel(); // Méthode de prélèvement $prelevement->getNatureProduit(); // NatureProduit Enum (123 valeurs) $prelevement->getUsageProduit(); // UsageProduit Enum (7 valeurs) $prelevement->getNormeProduit(); // Norme du produit $prelevement->getPreleveur(); // Preleveur $prelevement->getPayeur(); // Payeur $prelevement->getMesuresEnvironnementales(); // MesureEnvironnementale[] $prelevement->getEchantillons(); // Echantillon[] $prelevement->getCommemoratifs(); // Commemoratif[]
Echantillon
Représente un échantillon prélevé.
$echantillon->getRefEchantillonCommanditaire(); // Référence commanditaire $echantillon->getRefEchantillonPrel(); // Référence préleveur $echantillon->getRefEchantillonLabo(); // Référence laboratoire $echantillon->getGroupesParametres(); // GroupeParametresRef[] - Groupes de paramètres $echantillon->getLaboratoire(); // Laboratoire $echantillon->getPayeur(); // Payeur $echantillon->getMethodeTransport(); // Méthode de transport $echantillon->getAnalyses(); // Analyse[] - Analyses spécifiques $echantillon->getCommemoratifs(); // Commemoratif[]
🔧 Gestion des erreurs
Le bundle implémente une hiérarchie d'exceptions conforme aux préconisations SANDRE pour la gestion des erreurs dans les fichiers d'échange. Chaque exception correspond à un code d'erreur SANDRE (E0 à E4) avec sa définition officielle.
Hiérarchie des exceptions SANDRE
Toutes les exceptions héritent de SandreException
qui fournit :
getErrorCode()
: Retourne le code SANDRE (E0, E1, E2, E3, E4)getErrorDefinition()
: Retourne la définition complète selon SANDREgetMessage()
: Message préfixé automatiquement avec[E0]
,[E1]
, etc.
E0_FileCorruptedException - Fichier endommagé
Code E0 : Fichier XML endommagé, non lisible (lors de sa génération ou de son transport).
Le fichier XML en tant que tel est endommagé. L'application ne peut ouvrir ou lire le contenu du fichier.
use YoanBernabeu\EdilaboBundle\Exception\E0_FileCorruptedException; try { $comLabo = $edilabo->parseFile('/path/to/file.xml'); } catch (E0_FileCorruptedException $e) { // Fichier introuvable, non lisible ou corrompu echo $e->getErrorCode(); // "E0" echo $e->getMessage(); // "[E0] Fichier XML introuvable : /path/to/file.xml" }
Méthodes disponibles :
fileNotFound($path)
- Fichier introuvablefileNotReadable($path)
- Fichier non lisiblecorruptedFile($path, $reason)
- Fichier corrompusystemError($message)
- Erreur système
E1_MalformedXmlException - XML mal formaté
Code E1 : Fichier XML mal formaté (well-formed).
La structure du fichier XML ne respecte pas les spécifications XML sur sa structuration (balise de fermeture manquante, etc.).
use YoanBernabeu\EdilaboBundle\Exception\E1_MalformedXmlException; try { $comLabo = $edilabo->parse($xmlContent); } catch (E1_MalformedXmlException $e) { // XML mal formé (balises non fermées, structure incorrecte, etc.) echo $e->getErrorCode(); // "E1" echo $e->getMessage(); // "[E1] XML mal formaté : ..." }
Méthodes disponibles :
malformed($reason)
- XML mal formatéinvalidStructure($details)
- Structure XML invalideemptyContent()
- Contenu XML videmissingTag($tagName)
- Balise manquantefromLibXmlErrors($errors)
- À partir d'erreurs libxml
E2_SchemaValidationException - Non conforme au scénario
Code E2 : Fichier XML non validé au regard d'un scénario (valid).
Le fichier n'est pas valide au regard du scénario d'échanges SANDRE auquel il se réfère (erreurs de structure, non-respect des codes de valeurs possibles pour les nomenclatures).
use YoanBernabeu\EdilaboBundle\Exception\E2_SchemaValidationException; try { $edilabo->validateWithXsd($xmlContent); } catch (E2_SchemaValidationException $e) { // Non conforme au schéma XSD SANDRE echo $e->getErrorCode(); // "E2" echo $e->getMessage(); // "[E2] Validation XSD échouée : ..." }
Méthodes disponibles :
invalidScenario($validationErrors)
- Scénario invalideinvalidCodeValue($element, $value, $allowedValues)
- Valeur de code invalidemissingRequiredElement($parent, $element)
- Élément requis manquantxsdValidationFailed($errors)
- Validation XSD échouéeinvalidNamespace($expected, $actual)
- Namespace invalide
E3_UnknownReferenceException - Référence inconnue
Code E3 : Code/Identifiant non reconnu au niveau du référentiel commun.
Le fichier contient une valeur d'un code ou d'un identifiant non reconnu au niveau du référentiel commun SANDRE auquel il se rapporte.
use YoanBernabeu\EdilaboBundle\Exception\E3_UnknownReferenceException; try { // Si votre logique métier valide les codes SANDRE if (!$this->referentielSandre->exists($codeParametre)) { throw E3_UnknownReferenceException::unknownParameter($codeParametre); } } catch (E3_UnknownReferenceException $e) { // Code ou identifiant non reconnu dans le référentiel SANDRE echo $e->getErrorCode(); // "E3" echo $e->getMessage(); // "[E3] Paramètre SANDRE non reconnu : 1234" }
Méthodes disponibles :
unknownCode($element, $code, $referentiel)
- Code non reconnuunknownIdentifier($element, $identifier, $referentiel)
- Identifiant non reconnuunknownParameter($code)
- Paramètre SANDRE inconnuunknownMethod($code)
- Méthode SANDRE inconnueunknownUnit($code)
- Unité SANDRE inconnueunknownIntervenant($id)
- Intervenant introuvableunknownStation($code)
- Station introuvable
E4_UnsupportedContentException - Contenu non supporté
Code E4 : Contenu d'un élément ou attribut non supporté.
En raison des règles de gestion d'intégration (contraintes métiers, règles d'intégrité), l'information d'un élément ou attribut n'a pas de sens, l'erreur pouvant survenir au regard des autres informations contenues dans le fichier (inconsistent), ou au niveau de l'interface d'intégration.
use YoanBernabeu\EdilaboBundle\Exception\E4_UnsupportedContentException; try { // Si vos règles métier détectent une incohérence if ($prelevement->getDatePrel() > date('Y-m-d')) { throw E4_UnsupportedContentException::businessRuleViolation( 'DatePrelevement', $prelevement->getDatePrel(), 'La date de prélèvement ne peut être dans le futur' ); } } catch (E4_UnsupportedContentException $e) { // Violation de règle métier ou données incohérentes echo $e->getErrorCode(); // "E4" echo $e->getMessage(); // "[E4] Violation de règle métier pour ..." }
Méthodes disponibles :
businessRuleViolation($element, $value, $rule)
- Violation de règle métierinconsistentData($context, $reason)
- Données incohérentesintegrationError($element, $reason)
- Erreur d'intégrationunsupportedValue($element, $value, $reason)
- Valeur non supportéeintegrityConstraintViolation($constraint, $details)
- Violation de contrainte d'intégritéconflictingData($element1, $element2, $reason)
- Données en conflit
Exemple complet de gestion des erreurs
use YoanBernabeu\EdilaboBundle\EdilaboInterface; use YoanBernabeu\EdilaboBundle\Exception\E0_FileCorruptedException; use YoanBernabeu\EdilaboBundle\Exception\E1_MalformedXmlException; use YoanBernabeu\EdilaboBundle\Exception\E2_SchemaValidationException; use YoanBernabeu\EdilaboBundle\Exception\SandreException; try { $comLabo = $edilabo->parseFile('/path/to/commande.xml'); // Traitement des données... } catch (E0_FileCorruptedException $e) { // E0 : Fichier endommagé ou introuvable $this->logger->error($e->getMessage(), [ 'code' => $e->getErrorCode(), 'definition' => $e->getErrorDefinition() ]); } catch (E1_MalformedXmlException $e) { // E1 : XML mal formaté $this->logger->error($e->getMessage()); } catch (E2_SchemaValidationException $e) { // E2 : Non conforme au schéma SANDRE $this->logger->warning($e->getMessage()); } catch (SandreException $e) { // Capture toutes les autres exceptions SANDRE (E3, E4) $this->logger->error("Erreur SANDRE {$e->getErrorCode()}: {$e->getMessage()}"); }
Conformité SANDRE
Cette hiérarchie d'exceptions est conforme aux préconisations du scénario d'échange SANDRE Laboratoires-Commanditaires (page 69/79) qui définit les 5 types d'erreurs (E0 à E4) pouvant survenir lors du traitement d'un fichier d'échange.
🧪 Tests
Le bundle inclut des tests unitaires et d'intégration.
# Tests rapides (sans validation XSD - recommandé pour le développement) composer test:fast # Tous les tests (inclut validation XSD - plus lent) composer test:all # Tests unitaires seulement composer test:phpunit # Tests rapides (exclut les tests XSD lents) composer test:phpunit:fast # Tests de validation XSD uniquement composer test:phpunit:xsd # Analyse statique composer test:phpstan # Vérification du style de code composer test:cs
💡 Conseil : Utilisez
composer test:fast
pendant le développement (17ms) etcomposer test:all
avant de commiter (~1min avec validation XSD).
📦 Dépendances
- PHP 8.1 ou supérieur
- Symfony 7.3 ou supérieur
- symfony/serializer-pack
📝 Format supporté
Ce bundle supporte 100% du format SANDRE COM_LABO version 1.1 (Novembre 2015) défini dans le scénario d'échange "Echanges Laboratoires-Commanditaires - Message Demande de prestations".
Couverture complète
Le bundle implémente tous les éléments du schéma XSD, incluant :
- ✅ Tous les champs obligatoires et optionnels
- ✅ Toutes les cardinalités (éléments simples et tableaux)
- ✅ Tous les objets imbriqués (Service, LocalPrelevement, MesureEnvironnementale, etc.)
- ✅ Tous les champs spécialisés (méthodes de fractionnement, extraction, solvants, etc.)
- ✅ Validation XSD stricte contre le schéma officiel SANDRE
- ✅ 11 Enums PHP couvrant 314 valeurs de nomenclatures SANDRE pour la sécurité des types
Namespaces XML supportés
http://xml.sandre.eaufrance.fr/scenario/com_labo/1
Schéma XSD officiel
Le bundle utilise le schéma XSD officiel SANDRE :
- URL : https://xml.sandre.eaufrance.fr/scenario/com_labo/1/sandre_sc_com_labo.xsd
- Version : 1.1 (Mise à jour : 2014-09-04)
📄 Licence
MIT
👤 Auteur
Yoan Bernabeu
- Email: yoan.bernabeu@gmail.com
- GitHub: @yoanbernabeu