Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Product Attribute: loyalty_points_multiplier am Produkt anlegen

Product Attribute: loyalty_points_multiplier am Produkt anlegen

~7 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026

Block 2 hat mit der Reward-Entity eine vollkommen neue EAV-Entität gebaut - eigene Tabellen, eigener Entity Type, eigenes Model/ResourceModel-Paar. Block 3 braucht nichts davon: catalog_product existiert längst als vollwertige EAV-Entität, komplett mit eav_entity_type-Eintrag, Attribut-Sets und den bekannten Wertetabellen catalog_product_entity_decimal & Co. Ein neues Produkt-Attribut ist deshalb ungleich einfacher als eine neue Entity: nur ein einziger Aufruf von EavSetup::addAttribute() auf einen bereits existierenden Entity-Type-Code.

Kein neuer Entity Type - nur ein Attribut

loyalty_points_multiplier (Typ decimal, Default 1.0) legt fest, mit welchem Faktor die Grundpunktzahl eines Produkts multipliziert wird - Kapitel 5 hat den Parameter $productMultiplier in PointsCalculator::calculatePoints() bereits genau für dieses Attribut vorgesehen. Ein Wert von 2.0 bedeutet "doppelte Punkte", ein Wert von 0.0 bedeutet "dieses Produkt bringt trotz Kauf keine Punkte".

app/code/Mironsoft/Loyalty/Setup/Patch/Data/InstallProductLoyaltyAttribute.php
<?php

declare(strict_types=1);

namespace Mironsoft\Loyalty\Setup\Patch\Data;

use Magento\Catalog\Model\Product;
use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

/**
 * Registers the loyalty_points_multiplier decimal attribute on catalog_product.
 */
class InstallProductLoyaltyAttribute implements DataPatchInterface
{
    /**
     * @param ModuleDataSetupInterface $moduleDataSetup Provides the setup connection for the patch.
     * @param EavSetupFactory $eavSetupFactory Creates the EavSetup helper used to register the attribute.
     */
    public function __construct(
        private readonly ModuleDataSetupInterface $moduleDataSetup,
        private readonly EavSetupFactory $eavSetupFactory
    ) {
    }

    /**
     * Adds the loyalty_points_multiplier attribute to the existing catalog_product entity.
     *
     * @return void
     */
    public function apply(): void
    {
        $this->moduleDataSetup->getConnection()->startSetup();

        /** @var \Magento\Eav\Setup\EavSetup $eavSetup */
        $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);

        $eavSetup->addAttribute(Product::ENTITY, 'loyalty_points_multiplier', [
            'type' => 'decimal',
            'label' => 'Loyalty Points Multiplier',
            'input' => 'text',
            'required' => false,
            'default' => '1.0000',
            'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
            'group' => 'General',
            'sort_order' => 100,
            'visible' => true,
            'user_defined' => true,
            'apply_to' => '',
            'used_in_product_listing' => true,
        ]);

        $this->moduleDataSetup->getConnection()->endSetup();
    }

    /**
     * @return array<int, string>
     */
    public static function getDependencies(): array
    {
        return [];
    }

    /**
     * @return array<int, string>
     */
    public function getAliases(): array
    {
        return [];
    }
}

Die wichtigsten Array-Schlüssel im Überblick

  • type - der backend_type, bestimmt, in welche Wertetabelle (catalog_product_entity_decimal) der Wert geschrieben wird, exakt das Konzept aus Kapitel 14.
  • apply_to - eine leere Zeichenkette bedeutet "für alle Produkttypen sichtbar"; eine kommagetrennte Liste wie 'simple,virtual,configurable' würde das Attribut z. B. bei Gruppierten Produkten ausblenden.
  • global - der Scope, hier bewusst SCOPE_GLOBAL als Startpunkt; Kapitel 25 begründet, warum das für dieses konkrete Attribut später auf SCOPE_WEBSITE geändert wird.
  • used_in_product_listing - erlaubt dem Produkt-Collection-Loader im Frontend/Layer-Navigation-Kontext, den Wert ohne expliziten addAttributeToSelect()-Aufruf performant mitzuladen.

Achtung: addAttribute() ordnet ein neues Attribut standardmäßig nur dem Attribut-Set Default zu. Existieren im Shop bereits weitere Attribut-Sets (z. B. für unterschiedliche Produktkategorien), taucht loyalty_points_multiplier dort nicht automatisch auf - das erfordert einen zusätzlichen Durchlauf über $eavSetup->getAllAttributeSetIds(Product::ENTITY) mit je einem addAttributeToSet()-Aufruf, oder eine manuelle Zuordnung im Admin unter Stores > Attribute Set.

Modul-Abhängigkeit Magento_Catalog ergänzen

catalog_product stammt aus Magento_Catalog - dieselbe Überlegung wie in Kapitel 2 (Magento_Customer, Magento_Sales) und Kapitel 11 (Magento_Eav) gilt auch hier: ohne sequence-Eintrag besteht keine Garantie, dass catalog_product beim Ausführen dieses Patches bereits existiert.

app/code/Mironsoft/Loyalty/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Mironsoft_Loyalty">
        <sequence>
            <module name="Magento_Customer"/>
            <module name="Magento_Sales"/>
            <module name="Magento_Eav"/>
            <module name="Magento_Catalog"/>
        </sequence>
    </module>
</config>
bin/magento setup:upgrade
bin/magento indexer:reindex catalog_product_attribute
bin/magento cache:flush

Tipp: Nach jedem neuen oder geänderten Katalog-Attribut lohnt ein gezielter Reindex von catalog_product_attribute statt eines vollständigen indexer:reindex - bei großen Katalogen ein spürbarer Zeitunterschied, und bin/cache-clean (CLAUDE.md) übernimmt anschließend den Hyvä-Watcher-Teil, falls Frontend-Templates ebenfalls betroffen sind.

Mit loyalty_points_multiplier am Produkt folgt Kapitel 20 demselben Muster für die Kategorie - mit einem wichtigen Unterschied beim Standard-Scope, den Kapitel 25 später aufgreift.