Apparence
Commande & checkout
Le tunnel de commande appartient au front ; le cœur possède la transformation panier → commande et l'agrégation des choix. Voici comment l'étendre.
Le tunnel : des étapes
Le frontend enregistre des étapes dans le CheckoutStepRegistry (un registre), triées par priorité — par défaut user (10), addresses (20), shipping (30), payment (40).
Ajouter une étape :
php
use Slab\Frontend\Checkout\Contracts\CheckoutStepRegistry;
$this->app->make(CheckoutStepRegistry::class)->add('cadeau', GiftStepController::class, priority: 25);Réordonner sans code : config/checkout.php. Remplacer toute l'orchestration : bind le contrat CheckoutFlow.
Les choix : des options en donnée
Une feature qui ajoute un choix (transporteur, paiement) n'expose que de la donnée via un CheckoutOptionProvider — jamais de HTML. Elle décrit une exigence (shipping, payment…) et renvoie des options (id, libellé, prix, méta). Le frontend les rend génériquement :
php
use Slab\Framework\Core\Checkout\Contracts\CheckoutOptionRegistry;
$this->app->make(CheckoutOptionRegistry::class)->register(MonOptionProvider::class);Ajouter un transporteur le fait apparaître au checkout, sans toucher au front. C'est le modèle de slab/carrier et slab/payment.
La commande : un snapshot immuable
À la dernière étape, CartService::createOrder() délègue à l'OrderPlacementPipeline — une classe final, transactionnelle et idempotente (la contrainte unique orders.cart_id interdit de convertir deux fois le même panier). En une transaction, il :
- crée l'en-tête de commande (adresses répliquées,
checkout_selectionscopiées, jeton unique) ; - fige les lignes dans des
OrderProduct(référence, nom, quantité, prix HT/TTC du moment) ; - fige les totaux dans
price_components(JSON) + des colonnes, en devise de référence et du client ; - émet
OrderPlaced.
Résultat : une commande se relit sans aucun package installé (l'OrderPriceService lit les colonnes figées, sans jamais recalculer). Supprimer un transporteur après coup ne change pas une commande passée. Le pipeline n'est pas extensible directement — on s'y branche par l'événement.
Réagir à une commande
Pour réagir, écoutez les événements :
| Événement | Pour… |
|---|---|
OrderPlaced | e-mail, stock, ERP, fidélité |
OrderStatusChanged | notifications de suivi |
Points d'extension de ce domaine
| Je veux… | Point d'extension |
|---|---|
| ajouter une étape de tunnel | CheckoutStepRegistry (frontend) |
| ajouter un mode de livraison / paiement | CheckoutOptionProvider |
| changer l'orchestration du tunnel | CheckoutFlow (bind) |
| réagir à une commande | OrderPlaced, OrderStatusChanged |
greffer une relation sur Order | resolveRelationUsing |