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

EAV Attribute Types in Detail: varchar, int, decimal, text for Rewards

EAV Attribute Types in Detail: varchar, int, decimal, text for Rewards

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

The type key in the addAttribute() call from chapter 13 looks harmless, but it decides an attribute's entire read and write path: it ends up unchanged as backend_type in eav_attribute, and that determines which of the five value tables from chapter 11 AbstractEntity writes to on save.

The four backend_type values actually in use

  • varchar - title, reward_type. Short strings up to 255 characters, end up in mironsoft_loyalty_reward_entity_varchar.
  • text - description. Arbitrarily long text, ends up in mironsoft_loyalty_reward_entity_text (SQL column type TEXT, no length cap like varchar).
  • int - points_cost, is_active. Whole numbers, end up in mironsoft_loyalty_reward_entity_int - even the boolean is_active is an int at the database level, not a dedicated boolean type.
  • decimal - discount_value. Ends up in mironsoft_loyalty_reward_entity_decimal, SQL type DECIMAL(20,4) - exact, unlike float/double, which are fundamentally unsuited for monetary values.

Tipp: datetime is set up as the fifth table (chapter 11) but used by none of the six current attributes. That's exactly the practical benefit from chapter 10: a future attribute like valid_until (a reward's expiry date) would only need one more addAttribute() call in a new data patch - no schema change, no new table.

frontend_input is not backend_type

Two different concepts that are easy to confuse: backend_type decides where the value lives, frontend_input decides which form field is shown in the admin. is_active makes this clear: backend_type = int, but frontend_input = boolean - a checkbox in the admin, stored as 0/1 in an _int row. reward_type the same way: backend_type = varchar, but frontend_input = select, with the RewardType source model from chapter 13 supplying the options.

Writing and reading values

From the outside, the model behaves just like the flat ledger entity from chapter 4 - AbstractModel provides magic getters/setters via getData()/setData(). The difference lives entirely in the resource model, not in calling code:

$reward = $this->rewardFactory->create();
$reward->setIdentifier('reward-10-euro-voucher');
$reward->setTitle('10 Euro Discount Voucher');
$reward->setDescription('Redeemable starting at 500 points.');
$reward->setPointsCost(500);
$reward->setDiscountValue('10.0000');
$reward->setRewardType(RewardType::TYPE_DISCOUNT);
$reward->setIsActive(true);

$this->rewardResource->save($reward);

// Six separate INSERTs/UPDATEs behind the scenes: one on the main table,
// one per set attribute on the matching value table.

$loadedReward = $this->rewardFactory->create();
$this->rewardResource->load($loadedReward, $reward->getEntityId());
echo $loadedReward->getPointsCost(); // int(500)
echo $loadedReward->getDiscountValue(); // string("10.0000")

Achtung: Magento returns decimal attributes as a string ("10.0000"), not a PHP float - specifically to avoid rounding errors on monetary values. Anyone using the value directly in an arithmetic operation should use bcmath functions (bcadd(), bcmul()) or at least a deliberate, explicit type cast - never silently do arithmetic with + on a string read from an EAV table.

What this means for choosing a column type

The type value isn't a formality, it's a real architectural decision per attribute: varchar for short, searchable strings, text only for genuinely long content (a varchar field with 255 characters for description would simply truncate longer descriptions), int for whole numbers and booleans, decimal for anything involving money or percentages. A wrong choice can technically be corrected via a new data patch (changeAttribute() with a new backend_type), but that then requires migrating existing values between two value tables - effort that the right choice in chapter 13 avoids entirely.

With the attributes cleanly typed and populatable, chapter 15 tackles how to efficiently load several rewards at once - filtered by exactly these attributes.