Décoration de services
Utilisez la décoration de services Symfony lorsque vous devez ajouter un comportement autour d’un service Vavang unique sans remplacer son implémentation complète.
Exemple : décorer la génération Factur-X
FacturXGeneratorInterface est aliasée par le plugin vers son générateur par défaut. L’application hôte peut décorer l’identifiant de service de cette interface :
<?php
declare(strict_types=1);
namespace App\Invoice;
use SyliusInvoicePlugin\ElectronicInvoice\ElectronicInvoice;
use SyliusInvoicePlugin\FacturX\FacturXGeneratorInterface;
use SyliusInvoicePlugin\FacturX\GeneratedFacturXDocument;
final readonly class AuditingFacturXGenerator implements FacturXGeneratorInterface
{
public function __construct(private FacturXGeneratorInterface $inner)
{
}
public function generate(ElectronicInvoice $invoice, string $sourcePdfContent): GeneratedFacturXDocument
{
$document = $this->inner->generate($invoice, $sourcePdfContent);
// Observez ou journalisez ici des informations propres au projet.
// Ne modifiez pas la charge fiscale générée après validation.
return $document;
}
}
# config/services.yaml
services:
App\Invoice\AuditingFacturXGenerator:
decorates: SyliusInvoicePlugin\FacturX\FacturXGeneratorInterface
arguments:
$inner: '@App\Invoice\AuditingFacturXGenerator.inner'
Cette approche conserve l’implémentation du plugin derrière l’interface publique et évite de dépendre du constructeur concret de HorstoekoFacturXGenerator.
Exemple : ajouter une règle métier
ElectronicInvoiceBusinessRuleInterface est un point d’extension par collection consommé via le tag sylius_invoice.business_rule. La règle _instanceof du bundle s’applique aux services chargés par le plugin lui-même ; elle ne tagge pas globalement les règles métier déclarées par l’application hôte.
Déclarez donc le tag explicitement :
<?php
declare(strict_types=1);
namespace App\Invoice;
use SyliusInvoicePlugin\ElectronicInvoice\ElectronicInvoice;
use SyliusInvoicePlugin\Validation\BusinessRule\ElectronicInvoiceBusinessRuleInterface;
final class ProjectBusinessRule implements ElectronicInvoiceBusinessRuleInterface
{
public function validate(ElectronicInvoice $invoice): array
{
return [];
}
}
services:
App\Invoice\ProjectBusinessRule:
tags: ['sylius_invoice.business_rule']
La même règle de tag explicite s’applique aux implémentations hôtes des familles transmission, reporting de paiement et webhooks documentées dans Points d’extension. Les connecteurs et opérations plateforme sont différents : leurs interfaces sont enregistrées pour l’autoconfiguration par l’extension du bundle.
Remplacer uniquement quand la décoration ne suffit pas
Le remplacement d’un alias est possible pour des contrats comme SellerCompanyProviderInterface, VariantProductNatureResolverInterface, ElectronicDocumentValidatorInterface ou ComplianceDocumentStoreInterface. Une implémentation de remplacement prend en charge l’intégralité du contrat et doit préserver tous les invariants attendus par la chaîne de conformité.
Préférez la décoration pour le logging, les métriques, la réplication ou des contrôles additionnels. Réservez le remplacement aux cas où le comportement par défaut ne peut réellement pas convenir au projet.
Risque de BC
Ne décorez pas une classe concrète uniquement parce qu’elle est actuellement enregistrée comme service public du conteneur. Les dépendances de son constructeur peuvent évoluer. L’identifiant de service de l’interface documentée constitue la frontière la plus sûre.