Zusammenfassung: eigene Produkttypen richtig einführen
Zusammenfassung: eigene Produkttypen richtig einführen
~5 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026
Block 9 endet wie Block 6 mit Kapitel 54, Block 7 mit Kapitel 61 und Block 8 mit Kapitel 70: eine gesammelte Rückschau - diesmal auf den kompletten Weg von der Entscheidungsfrage in Kapitel 71 bis zur einlösbaren, rabattfähigen Bestellung in Kapitel 77.
Alle Dateien dieses Blocks im Überblick
Neue und geänderte Dateien aus Block 9
app/code/Mironsoft/Loyalty/
├── Model/
│ └── Product/
│ └── Type/
│ ├── PointsPackage.php (Kapitel 73)
│ └── PointsPackage/
│ └── Price.php (Kapitel 73)
├── Observer/
│ └── CreditPurchasedPointsPackageOnOrderPlaced.php (Kapitel 76)
├── Setup/
│ └── Patch/
│ └── Data/
│ ├── InstallPointsPackageAttributeSet.php (Kapitel 74)
│ ├── InstallPointsPackageAmountAttribute.php (Kapitel 74)
│ └── InstallSalesLoyaltyPointsPackageCreditedAttribute.php (Kapitel 76)
├── etc/
│ ├── product_types.xml (Kapitel 72)
│ └── events.xml (Kapitel 76, erweitert)
└── view/
├── adminhtml/
│ └── ui_component/
│ └── product_form.xml (Kapitel 74, optional)
└── frontend/
├── layout/
│ └── catalog_product_view_type_loyalty_points_package.xml (Kapitel 75)
└── templates/
└── product/
└── view/
└── type/
└── points-package.phtml (Kapitel 75)Checkliste: eigene Produkttypen einführen
- Entscheidung begründen (Kapitel 71): Reicht ein Attribut auf einem bestehenden Typ, oder braucht das Konzept eine eigene
apply_to-Abgrenzung? - Registrieren (Kapitel 72):
etc/product_types.xmlmitmodelInstance,priceModel,indexPriceModel- Cache leeren, in Productionsetup:di:compile. - Type- und Price-Model implementieren (Kapitel 73): passende Elternklasse wählen (hier
Virtual), nur das wirklich Abweichende überschreiben. - Admin-Formular vorbereiten (Kapitel 74): eigenes Attribut-Set, Pflichtfelder mit
apply_to-Scoping, Attribut-Set UND Typ zusammen kommunizieren. - Frontend anzeigen und verkaufen (Kapitel 75): automatischen Layout-Handle nutzen, generische
additional_optionsstatt neuer Cart-/Order-Templates. - Bestellabwicklung verzahnen (Kapitel 76): Observer statt Plugin, eigenes Idempotenz-Attribut, bestehende Repository-Schnittstellen aus Block 1 wiederverwenden statt neu zu erfinden.
- Kompatibilität testen (Kapitel 77): vollständiger Reindex nach Einführung, Preisregeln und Drittanbieter-Kampagnen gezielt end-to-end durchklicken statt anzunehmen, dass sie funktionieren.
Tipp: Der rote Faden durch alle acht Kapitel dieses Blocks: ein neuer Produkttyp ist fast nie "neu" im Sinne von "komplett neu geschrieben" - PointsPackage erbt von Virtual, das Price-Model erbt vom Core-Price, die Bestellabwicklung nutzt PointsLedgerRepositoryInterface und CustomerRepositoryInterface aus Block 1 unverändert weiter. Was diesen Typ tatsächlich neu macht, ist ausschließlich der distincte Typ-Code selbst und die wenigen Stellen, an denen sich das Geschäftskonzept - ein kaufbares Bündel Treuepunkte - wirklich von allem bereits Vorhandenen unterscheidet.
Block 10 wendet sich als Nächstes APIs zu: REST- und GraphQL-Endpunkte, die denselben Punktestand und dieselben Repositories - inklusive der in diesem Block neu verzahnten Punkte-Paket-Logik - für externe Clients zugänglich machen.