Skip to content

Le conteneur & les contrats

C'est la mécanique de base : presque tout comportement du cœur passe par un contrat (une interface) lié à une implémentation par défaut dans le conteneur Laravel. Vous pouvez la remplacer ou la décorer — sans jamais éditer le cœur.

Le problème

Vous voulez changer comment Slab fait quelque chose : résoudre la devise autrement, calculer la taxe selon vos règles, remplacer un service. Éditer vendor/slab/framework est exclu — perdu à la prochaine mise à jour. Il faut un point de bascule depuis l'extérieur.

Le principe

Le cœur ne dépend jamais d'une classe concrète : il dépend d'une interface, et lie un défaut dans le conteneur.

Vous redirigez l'interface vers votre implémentation. Tout le cœur l'utilise aussitôt, sans le savoir.

Remplacer une implémentation

Dans le boot() (ou register()) d'un provider — celui de votre app ou d'un package :

php
use Slab\Framework\Core\Tax\Contracts\TaxResolver;

$this->app->bind(TaxResolver::class, MonTaxResolver::class);

Votre classe doit implémenter l'interface :

php
use Slab\Framework\Core\Tax\Contracts\TaxResolver;
use Slab\Framework\Core\Tax\TaxRate;
use Slab\Framework\Models\{Area, TaxRule};

final class MonTaxResolver implements TaxResolver
{
    public function resolve(?TaxRule $taxRule, Area $area): TaxRate
    {
        // votre logique…
    }
}

Décorer plutôt que remplacer

Pour ajouter un comportement (cache, log, métrique) en gardant le défaut, décorez-le avec extend — l'implémentation d'origine vous est passée :

php
$this->app->extend(TaxResolver::class, function (TaxResolver $inner, $app) {
    return new TaxResolverAvecCache($inner); // délègue à $inner, met en cache
});

Les services de domaine (scopés à une entité)

Les services de domaine du cœur — le calcul du prix d'un produit, le panier, la commande — suivent exactement le même modèle : un contrat dans Contracts/, lié à un Default…. La seule particularité : certains sont scopés à une entité, donc résolus en passant l'entité en paramètre nommé.

php
use Slab\Framework\Core\Product\Contracts\ProductPriceService;

// Le cœur résout le service avec le produit concerné :
$price = app(ProductPriceService::class, ['product' => $product])->getMoney(ti: true);

Vous le remplacez comme n'importe quel contrat — votre implémentation reçoit l'entité au constructeur :

php
use Slab\Framework\Core\Product\Contracts\ProductPriceService;
use Slab\Framework\Models\Product;

final class PrixDegressifB2B implements ProductPriceService
{
    public function __construct(private Product $product) {}

    // getMoney(), getPrice(), addPrice()…
}

$this->app->bind(ProductPriceService::class, PrixDegressifB2B::class);

Liaison par chaîne de classe, pas par closure

Liez le contrat à sa classe (bind(Contrat::class, MaClasse::class)), pas à une closure : Laravel injecte alors automatiquement les paramètres nommés (['product' => $p]) au constructeur, et une nouvelle instance est rendue à chaque résolution (jamais partagée entre deux entités).

Le prix passe déjà par un pipeline

Pour ajuster un prix (remise, palier) sans réécrire le service, préférez un modificateur de prix : DefaultProductPriceService délègue au PricePipeline. Remplacer le service entier ne se justifie que pour changer la façade de calcul elle-même.

Où Slab l'utilise

Tous les contrats marqués « surchargeable » dans la référence suivent ce modèle. Les plus courants :

ContratRôle
CurrentCartResolverle panier courant
CurrentCurrencyResolverla devise d'affichage
CurrentAreaResolverla zone fiscale (pilote la taxe)
TaxResolverle taux de taxe pour une règle + une zone
PriceModifierRegistry, TotalsModifierRegistryles pipelines
BackMenuRegistry, RouteContributionRegistrar, ViewHookRegistryles registres
ProductPriceServicele prix d'un produit (service de domaine, scopé)

Comment savoir ce qui est remplaçable

La commande php artisan slab:extension-points (et la référence générée) liste chaque contrat, son domaine, son type (surchargeable = un défaut existe ; implémentable = à fournir par un package) et son implémentation par défaut.

Une règle d'or

N'éditez jamais un fichier sous vendor/slab/…. Tout se fait depuis l'extérieur : bind, decorate, contribuer, surcharger une vue. C'est ce qui garde vos mises à jour indolores.

Voir aussi