Registering the "Points Package" Product Type: etc/product_types.xml
Registering the "Points Package" Product Type: etc/product_types.xml
~5 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026
Chapter 71 justified the decision, chapters 73-76 build the actual logic - this chapter in between handles the pure registration: the one declaration that lets Magento know the type code loyalty_points_package exists at all.
product_types.xml as a configuration type
etc/product_types.xml is itself technically an example of what chapter 88 (block 11) introduces more generally as a configuration type: an XML structure merged across modules, read once, and cached afterwards - not a database value like System/Config/Setting (chapter 7). In practice, for this chapter that mainly means one thing: changes to this file need an explicit cache flush, more on that in a moment.
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Catalog:etc/product_types.xsd">
<type name="loyalty_points_package"
label="Punkte-Paket"
modelInstance="Mironsoft\Loyalty\Model\Product\Type\PointsPackage"
indexPriceModel="Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice"
priceModel="Mironsoft\Loyalty\Model\Product\Type\PointsPackage\Price"
isQty="true"
canUseQtyDecimals="false"
sortOrder="110"/>
</config>
The attributes in detail
name- the type code itself, from here on identical, character for character, to the constantPointsPackage::TYPE_CODE(chapter 73).modelInstance- the type model class chapter 73 implements next; without it, every action against this type code immediately fails with an exception.priceModel- the class responsible for price calculation, also chapter 73.indexPriceModel- deliberately the same default class used bysimple/virtual(DefaultPrice), since a points package needs no tier- or configuration-dependent price logic that would justify a dedicated price indexer - relevant for chapter 77.isQty- a quantity field is shown in the cart ("buy 3 points packages"), same assimple/virtual.canUseQtyDecimals- deliberatelyfalse: a fractional quantity like "1.5 points packages" is not a meaningful business concept.sortOrder-110, deliberately well above the core types (simple= 10,virtual= 20, etc.), so "Points Package" recognizably sits at the end of the "New Product" dropdown instead of squeezing between the core types.
Achtung: bin/cache-clean config is mandatory after every change to product_types.xml (the same config cache tag that etc/config.xml changes from chapter 62 also need) - without a cache flush, the new type simply stays invisible in the admin. In production mode, bin/magento setup:di:compile is also required, since the generated interception and object manager configuration otherwise doesn't know about the new type code.
Not functional yet
With just this one file, "Points Package" already shows up in the "New Product" dropdown - but clicking it immediately ends in a PHP exception, because Mironsoft\Loyalty\Model\Product\Type\PointsPackage and ...\PointsPackage\Price don't exist yet. Chapter 73 supplies exactly these two classes.