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

What Is EAV? Why a Custom EAV Entity Makes Sense for Rewards

What Is EAV? Why a Custom EAV Entity Makes Sense for Rewards

~6 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026

Block 1 deliberately built a plain, flat table with the points ledger: one column per property, a ResourceModel sitting directly on top of AbstractDb. Block 2 builds this series' second core entity - the reward - in a completely different way: as an EAV entity, following the same pattern as catalog_product_entity. Before chapter 11 designs the tables, it needs to be clear what EAV actually is, why Magento uses it for products, categories, and customers - and, just as important, when it's not worth it.

What is EAV?

EAV stands for Entity-Attribute-Value. Instead of adding a fixed column per property like a classic relational table would (title, points_cost, reward_type as columns in a single table - exactly the pattern the points ledger used), EAV stores every single property as its own row in a separate table: one row per combination of entity, attribute, and value.

  • Entity - the main row in the main table, here mironsoft_loyalty_reward_entity, with a small, fixed set of core columns (entity_id, attribute_set_id, identifier, and so on).
  • Attribute - a property like title or points_cost, defined as a record in the central eav_attribute table provided by Magento_Eav, not as a table column.
  • Value - the actual value of an entity for an attribute, stored in one of five value tables, split by PHP scalar type (_varchar, _int, _decimal, _text, _datetime).

Reading the title and points cost of a single reward therefore doesn't take a single row from a single table, but the main row plus one row each from mironsoft_loyalty_reward_entity_varchar (for title) and mironsoft_loyalty_reward_entity_int (for points_cost) - joined on entity_id.

Why does Magento use EAV for products and customers?

The reason isn't academic, it's practical: catalog_product, catalog_category, and customer have a heavily variable number of attributes - a T-shirt has a size and a color, a book has an author and an ISBN, a B2B customer has a company assignment, a retail customer doesn't. New attributes also need to be addable without a code deployment - a shop operator adds a new product attribute in the admin without anyone running ALTER TABLE or deploying a module. That's exactly EAV's strength: new attributes are pure data (a row in eav_attribute), not a schema change.

Tipp: This strength has a name: extensibility without migration. Anyone who has ever added a new product attribute in a live Magento shop via Stores > Attributes > Product has seen EAV in action - without ever noticing it.

Does EAV actually fit a reward?

Honest answer: not necessarily. The reward in this series has exactly six fixed, predefined attributes (title, description, points_cost, discount_value, reward_type, is_active) - no attribute sets with wildly different properties like the product catalog, no fields the shop operator can freely add at runtime. A plain, flat table following the points ledger pattern from block 1 would be technically just as viable - with the benefit of noticeably simpler and faster queries.

Two reasons justify the EAV decision anyway, and both are real, not just didactic: first, a reward catalog is exactly the kind of entity that, in a growing shop, typically accumulates additional, merchant-specific attributes over time - a seasonal flag, a minimum loyalty tier, a reference to a specific product, an extra image - without every such extension justifying a new module release. Second, "build a custom EAV entity" is one of the 32 requested module areas of this series (see chapter 1) - a topic that would stay abstract without a concrete, workable example.

Achtung: Reflexively reaching for EAV on every new entity just because Magento does it for products is one of the most common architecture mistakes in Magento projects. Chapter 18, at the end of this block, comes back to exactly this trade-off with concrete numbers - the decision from this chapter can then be evaluated again with more information.

The table structure at a glance

Tables of the reward EAV entity after block 2

mironsoft_loyalty_reward_entity            (main table, one row per reward)
mironsoft_loyalty_reward_entity_varchar     (title, reward_type)
mironsoft_loyalty_reward_entity_int         (points_cost, is_active)
mironsoft_loyalty_reward_entity_decimal     (discount_value)
mironsoft_loyalty_reward_entity_text        (description)
mironsoft_loyalty_reward_entity_datetime    (currently unused, reserved for future date attributes)

The EAV vocabulary for the rest of this block

  • Entity type - the unique code of an EAV entity in eav_entity_type, here mironsoft_loyalty_reward (chapter 13).
  • Attribute - a single property, defined in eav_attribute, with a backend_type (which value table) and a frontend_input (which admin form field) - chapters 13 and 14.
  • Attribute set and attribute group - a named grouping of attributes (a "Default" set with a "General" group is entirely sufficient for rewards) - chapter 13.
  • backend_type - an attribute's PHP scalar type (varchar, int, decimal, text, datetime), determines which of the five value tables the value ends up in - chapter 14.

The next three chapters build the foundation bottom-up: chapter 11 creates the tables themselves via db_schema.xml, chapter 12 writes the model and resource model for them, and chapter 13 registers the entity type and the six attributes via a setup script - only after that does an actually usable reward entity exist.