Apparence
Modèles & relations
Vos données (un programme de fidélité, des transactions, des avis…) doivent se relier aux modèles du cœur — Product, Cart, Order… — sans que le cœur connaisse vos modèles. La mécanique centrale est resolveRelationUsing.
Le problème
Le package « promotions » a une table promotions et veut écrire $product->promotions. Mais Product est dans le cœur, qui n'importe jamais Promotion. Comment ajouter une relation à un modèle qu'on n'a pas le droit de modifier ?
Greffer une relation
Au boot() du provider, on ré-attache la relation depuis l'extérieur — l'inverse exact du couplage cœur → feature :
php
use Slab\Framework\Models\Product;
Product::resolveRelationUsing('promotions',
fn (Product $product) => $product->belongsToMany(Promotion::class));L'appel comme méthode ($product->promotions()) et l'accès propriété ($product->promotions) fonctionnent. Tous les types de relations Eloquent sont possibles :
php
Order::resolveRelationUsing('transactions',
fn (Order $order) => $order->hasMany(Transaction::class));
TaxRule::resolveRelationUsing('carriers',
fn (TaxRule $rule) => $rule->hasMany(Carrier::class));C'est ainsi que slab/promotion, slab/payment et slab/carrier se branchent sur le cœur.
Modèles polymorphes : possédés par plusieurs entités
Certains modèles du cœur (Cart, Order, Address) appartiennent à plusieurs types via une relation morphTo — un User ou un Guest aujourd'hui. Une feature peut ajouter son propre type de propriétaire en l'enregistrant dans la morph map, sans toucher au cœur.
Étendre le comportement d'un modèle
Au-delà des relations, les modèles du cœur sont conçus pour être enrichis :
- Traits :
Activable(scope->active()),SoftDeletes,HasTranslations(champs multilingues JSON),HasContents(attributs éditoriaux),Searchable(indexation) — réutilisables sur vos propres modèles. - Attributs contentables : ajoutez des champs riches/traduits à
Product,User… sans migration viaHasContents.
Substituer un modèle du cœur
Choix de conception
Remplacer entièrement la classe d'un modèle du cœur (votre Product à la place du sien) n'est pas un point d'extension : ce serait spéculatif et coûteux (Laravel instancie les modèles par new, query, find, relations…), et les besoins réels sont déjà couverts — greffer des relations, enrichir via traits/contentable, réagir via événements, et stabiliser les types via la morph map (le vrai point d'extension prospectif, voir ci-dessus). Un modèle dérivé ciblé resterait possible plus tard si un besoin concret l'exigeait, conçu avec son consommateur — pas par avance.
Voir aussi
- Le conteneur & les contrats — pour remplacer un service.
- Créer un package — où votre schéma vit (migrations possédées).