REX Ibexa Commerce 4.6 : créer un produit avec variantes, prix et stock
Après une première boutique de démonstration basée sur des produits simples, nous avons voulu valider le fonctionnement réel des variantes dans Ibexa Commerce 4.6.32.
L'objectif était concret : créer un T-shirt physique disponible en deux couleurs et trois tailles, attribuer un prix et un stock à chaque combinaison, l'afficher dans le storefront puis terminer une commande avec une variante précise.
Le résultat a été testé de bout en bout : la variante noire en taille M a été commandée, son code exact a été enregistré dans la commande et son stock est passé de 10 à 9.
Le résultat obtenu
Notre produit possède deux axes de variation :
Color : Black, Blue
Size : S, M, L
Ibexa génère donc six variantes :
| Code | Couleur | Taille | Prix | Stock initial |
|---|---|---|---|---|
IBEXA-TSHIRT-BLACK-S |
Black | S | 29,90 € | 12 |
IBEXA-TSHIRT-BLACK-M |
Black | M | 29,90 € | 10 |
IBEXA-TSHIRT-BLACK-L |
Black | L | 31,90 € | 8 |
IBEXA-TSHIRT-BLUE-S |
Blue | S | 29,90 € | 11 |
IBEXA-TSHIRT-BLUE-M |
Blue | M | 29,90 € | 9 |
IBEXA-TSHIRT-BLUE-L |
Blue | L | 31,90 € | 7 |
1. Créer le groupe d'attributs
Un Attribute Group sert à organiser les définitions d'attributs dans le back-office. Il ne crée aucune variante à lui seul.
Nous avons créé le groupe Clothing avec une migration dédiée :
- type: attribute_group
mode: create
identifier: clothing
position: 10
names:
eng-GB: Clothing
Dans le back-office, ce groupe se trouve sous Product Catalog → Attribute Groups.
2. Créer Color et Size
L'attribut Color utilise le type natif color. Ses valeurs sont stockées sous forme de couleurs hexadécimales :
- type: attribute
mode: create
identifier: color
attribute_group_identifier: clothing
attribute_type_identifier: color
position: 0
names:
eng-GB: Color
options:
choices:
- value: '#000000'
label:
eng-GB: Black
- value: '#0000FF'
label:
eng-GB: Blue
Size est un attribut de sélection classique :
- type: attribute
mode: create
identifier: size
attribute_group_identifier: clothing
attribute_type_identifier: selection
position: 1
names:
eng-GB: Size
options:
choices:
- { value: S, label: { eng-GB: S } }
- { value: M, label: { eng-GB: M } }
- { value: L, label: { eng-GB: L } }
À ce stade, nous avons seulement défini des caractéristiques réutilisables. Elles ne deviennent des axes de variantes qu'au niveau du Product Type.
3. Créer le Product Type physique
Nous avons créé demo_tshirt dans le groupe de Content Types product. Son champ Product Specification contient l'affectation des attributs :
fieldSettings:
attributes_definitions:
clothing:
- { attributeDefinition: color, required: true, discriminator: true }
- { attributeDefinition: size, required: true, discriminator: true }
regions:
default:
region_identifier: default
vat_category_identifier: standard
Deux options sont importantes :
required: trueimpose une valeur ;discriminator: trueindique que l'attribut différencie les variantes.
La base a confirmé que le type est physique, avec is_virtual = 0, et que les deux affectations sont obligatoires et discriminantes.
4. Créer le produit de base
Le produit parent reçoit un code stable :
- type: content
mode: create
metadata:
contentType: demo_tshirt
mainTranslation: eng-GB
remoteId: demo_product_tshirt
alwaysAvailable: true
fields:
- fieldDefIdentifier: specification
languageCode: eng-GB
value:
code: IBEXA-TSHIRT
- fieldDefIdentifier: name
languageCode: eng-GB
value: 'Ibexa developer T-shirt'
Le produit parent porte les informations communes. Les codes vendables sont ensuite créés comme variantes.
5. Générer les six variantes
La migration product_variant reçoit le code du produit de base et les combinaisons d'attributs :
- type: product_variant
mode: create
base_product_code: IBEXA-TSHIRT
variants:
- code: IBEXA-TSHIRT-BLACK-M
attributes:
color: '#000000'
size: M
- code: IBEXA-TSHIRT-BLUE-M
attributes:
color: '#0000FF'
size: M
Le fichier réel contient les six combinaisons. Donner nous-mêmes les codes rend le résultat prévisible pour les imports, les tests et les intégrations externes.
6. Le piège rencontré lors de la republication
Après la génération, nous avons essayé de republier le contenu avec une migration content update ne contenant que le champ name. Ibexa a refusé la migration :
Value for required field definition 'specification' with language 'eng-GB' is empty.
La correction consiste à renvoyer également la valeur du champ Product Specification obligatoire :
- type: content
mode: update
match:
field: content_remote_id
value: demo_product_tshirt
fields:
- fieldDefIdentifier: specification
languageCode: eng-GB
value:
code: IBEXA-TSHIRT
- fieldDefIdentifier: name
languageCode: eng-GB
value: 'Ibexa developer T-shirt'
C'est un point important pour les migrations de mise à jour : un champ obligatoire non traduisible ne doit pas être oublié.
7. Ajouter prix et stock à chaque variante
Le prix et la disponibilité restent séparés de Product Specification :
- type: product_price
mode: create
product_code: IBEXA-TSHIRT-BLACK-M
currency_code: EUR
amount: 29.90
- type: product_availability
mode: create
product_code: IBEXA-TSHIRT-BLACK-M
is_available: true
is_infinite: false
stock: 10
Cette séparation autorise un prix et un stock différents pour chaque combinaison. Dans notre exemple, les tailles L coûtent 31,90 € et les autres 29,90 €.
8. Inclure le Product Type dans le catalogue
Notre catalogue initial filtrait uniquement demo_product. Le T-shirt existait donc dans la base mais n'appartenait pas encore à l'offre du storefront.
Nous avons élargi le critère :
new ProductType(['demo_product', 'demo_tshirt'])
Après la mise à jour du catalogue, nous avons réindexé :
php bin/console ibexa:reindex
Le catalogue public et la fiche produit ont ensuite répondu en HTTP 200.
9. Ajouter un vrai visuel produit
Nous avons remplacé l'image placeholder par une photo catalogue carrée : T-shirt noir, fond studio clair et motif géométrique rouge et bleu.
La commande de démo utilise LocalProductServiceInterface pour renseigner le champ image du produit parent. Les variantes héritent ainsi du visuel commun dans le storefront et le checkout.
10. Tester une vraie commande
Nous avons sélectionné la variante noire en taille M :
IBEXA-TSHIRT-BLACK-M
Le storefront a affiché :
- disponibilité :
In stock; - prix net : 29,90 € ;
- livraison standard : 5,90 € ;
- total avec taxes : 42,96 €.
Après validation du checkout, Ibexa a créé la commande de test en statut pending. Une vérification directe de la commande a confirmé :
product_code = IBEXA-TSHIRT-BLACK-M
quantity = 1
Le stock de cette variante est passé de 10 à 9. Cette dernière vérification prouve que le panier, le checkout, la commande et la disponibilité utilisent bien le code de variante, et non seulement le produit parent.
Les fichiers de la démonstration
Les étapes sont séparées pour rendre l'apprentissage et le diagnostic plus simples :
src/Migrations/Demo/
├── 06_clothing_attribute_group.yaml
├── 07_clothing_attributes.yaml
├── 08_tshirt_product_type.yaml
├── 09_tshirt_product_variants.yaml
├── 10_publish_tshirt_variants.yaml
└── 11_tshirt_variant_commerce.yaml
Cette séparation permet de comprendre précisément où interviennent le groupe, les définitions d'attributs, le Product Type, les variantes et les données commerciales.
Conclusion
Les variantes Ibexa Commerce ne sont pas de simples options visuelles sur une fiche produit. Chaque combinaison possède une véritable identité commerciale : code, prix, disponibilité et stock.
Le flux validé est le suivant :
Attribute Group
→ Attribute Definitions
→ Product Type avec discriminateurs
→ Produit parent
→ Variantes
→ Prix et stocks
→ Catalogue
→ Réindexation
→ Panier et commande
Ce test nous a également donné deux enseignements pratiques : toujours inclure Product Specification lors d'une mise à jour de contenu et toujours vérifier le filtre du catalogue lorsqu'un nouveau Product Type n'apparaît pas dans le storefront.
