Apparence
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 :
| Contrat | Rôle |
|---|---|
CurrentCartResolver | le panier courant |
CurrentCurrencyResolver | la devise d'affichage |
CurrentAreaResolver | la zone fiscale (pilote la taxe) |
TaxResolver | le taux de taxe pour une règle + une zone |
PriceModifierRegistry, TotalsModifierRegistry | les pipelines |
BackMenuRegistry, RouteContributionRegistrar, ViewHookRegistry | les registres |
ProductPriceService | le 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
- Les pipelines et les registres : des contrats particuliers, faits pour accumuler des contributions.
- Personnaliser le cœur pour les vues.