Types of Attributes
Deep dive into EAV and Extension attributes - understanding their differences, use cases, and implementation approaches for extending Magento entities.
Attribute Types Overview
The Power of Attributes in Magento
Attributes are an important feature of Magento. Many out-of-the-box features rely on attributes heavily, and it is possible to create new attributes to implement custom functionality.
Attributes are Functional, Not Just Data
Traditional Approach
Mere Data Elements:
- Just store information
- No behavior changes
- Static properties
- Limited functionality
Magento Attributes
Functional Elements:
- ✅ Change object behavior
- ✅ Trigger functionality
- ✅ Dynamic properties
- ✅ Rich feature set
Two Primary Types of Attributes
There are two primary types of attributes in Magento:
1. EAV Attributes
Traditional Entity-Attribute-Value attributes with automatic persistence and scope support.
2. Extension Attributes
Modern, flexible attributes for complex data types with manual implementation.
Comprehensive Comparison Table
| Feature | EAV Attribute | Extension Attribute |
|---|---|---|
| Applied to | A Resource model that extends Magento\Eav\Model\Entity\AbstractEntity |
Data model that extends Magento\Framework\Api\AbstractExtensibleObject, or model that extends Magento\Framework\Model\AbstractExtensibleModel |
| Values stored | In special tables with types *_entity_varchar, *_entity_int, and so on. For example: catalog_product_entity_int |
It is up to developer to decide where to store the data (custom tables, files, external APIs) |
| Save and load | Automatically implemented in the AbstractEntity resource model. A lot of functionality is implemented in Magento_Catalog abstract resource model |
Manually. Developer has to load and save the data using plugins or observers |
| Use for custom entity | Very difficult | Easy |
| Create new attribute | Requires a DataPatch | Requires an entry in etc/extension_attributes.xml file |
| Availability in WebAPI | Available as Custom Attributes | Available as Extension Attributes |
| Scope support | Out of the box for product and category attributes | Does not support scope out of the box, up to developer to implement |
| Grid and form support | Yes, out-of-the-box | No, requires custom work |
| Typical use case | Extend an entity with a new scalar property, implement some functionality when the property changes, support different values for different scopes | Extending an entity with a new property, not necessarily scalar, could be an object or array. Data is stored in custom tables, files, could even be fetched by API |
EAV Attributes In-Depth
Entity-Attribute-Value Architecture
EAV attributes follow the Entity-Attribute-Value pattern, where attribute values are stored separately from the main entity table.
Applied To
EAV attributes can only be applied to resource models that extend Magento\Eav\Model\Entity\AbstractEntity.
Core Entities Using EAV:
- ✅ Products -
Magento\Catalog\Model\ResourceModel\Product - ✅ Categories -
Magento\Catalog\Model\ResourceModel\Category - ✅ Customers -
Magento\Customer\Model\ResourceModel\Customer - ✅ Customer Addresses -
Magento\Customer\Model\ResourceModel\Address
Storage Structure
EAV attribute values are stored in special tables based on data type:
| Data Type | Table Pattern | Example (Product) |
|---|---|---|
| Text (short) | *_entity_varchar |
catalog_product_entity_varchar |
| Integer | *_entity_int |
catalog_product_entity_int |
| Decimal | *_entity_decimal |
catalog_product_entity_decimal |
| Text (long) | *_entity_text |
catalog_product_entity_text |
| Date/Time | *_entity_datetime |
catalog_product_entity_datetime |
entity_id, attribute_id, store_id, and value columns for scope-aware storage.
Automatic Save and Load
One of the biggest advantages of EAV attributes is automatic persistence.
<?php
// EAV attribute - automatically saved
$product->setWarrantyPeriod(12);
$product->save(); // warranty_period is automatically saved to catalog_product_entity_int
// Later, automatically loaded
$warrantyPeriod = $product->getWarrantyPeriod(); // Automatically loaded from database
AbstractEntity resource model. Lots of functionality is also in Magento_Catalog abstract resource model.
Creating EAV Attributes
EAV attributes require a DataPatch to create them.
<?php
namespace Vendor\Module\Setup\Patch\Data;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Catalog\Model\Product;
use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
class AddCustomAttribute implements DataPatchInterface
{
private $eavSetupFactory;
public function __construct(EavSetupFactory $eavSetupFactory)
{
$this->eavSetupFactory = $eavSetupFactory;
}
public function apply()
{
$eavSetup = $this->eavSetupFactory->create();
$eavSetup->addAttribute(
Product::ENTITY,
'warranty_period',
[
'type' => 'int',
'label' => 'Warranty Period (months)',
'input' => 'text',
'required' => false,
'sort_order' => 100,
'global' => ScopedAttributeInterface::SCOPE_STORE,
'visible' => true,
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'group' => 'General'
]
);
return $this;
}
public static function getDependencies()
{
return [];
}
public function getAliases()
{
return [];
}
}
Scope Support
EAV attributes for products and categories support scope out of the box.
Available Scopes:
- SCOPE_GLOBAL - Same value across all websites and store views
- SCOPE_WEBSITE - Different values per website
- SCOPE_STORE - Different values per store view
<?php
use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
// In DataPatch
'global' => ScopedAttributeInterface::SCOPE_STORE, // Store view scope
'global' => ScopedAttributeInterface::SCOPE_WEBSITE, // Website scope
'global' => ScopedAttributeInterface::SCOPE_GLOBAL, // Global scope
Grid and Form Support
EAV attributes have built-in support for admin grids and forms.
// In DataPatch attribute configuration
'is_used_in_grid' => true, // Can be used in admin grid
'is_visible_in_grid' => true, // Visible in admin grid by default
'is_filterable_in_grid' => true, // Can filter by this attribute in grid
'is_searchable_in_grid' => true, // Can search by this attribute
Use for Custom Entities
- Creating multiple database tables (*_entity, *_entity_int, *_entity_varchar, etc.)
- Implementing resource model extending
AbstractEntity - Setting up EAV entity type
- Managing attribute sets and groups
- Complex configuration and setup
Extension Attributes In-Depth
Flexible Extension Architecture
Extension attributes provide a flexible way to extend entities with complex data types and custom storage mechanisms.
Applied To
Extension attributes can be applied to:
- Data models that extend
Magento\Framework\Api\AbstractExtensibleObject - Models that extend
Magento\Framework\Model\AbstractExtensibleModel
Common Extensible Entities:
- ✅ Products, Categories, Customers (API Data interfaces)
- ✅ Orders, Quotes, Invoices, Shipments
- ✅ Cart items, Quote items
- ✅ Custom entities implementing the interfaces
Storage - Developer's Choice
Unlike EAV attributes, with extension attributes the developer decides where to store the data.
Storage Options:
- ✅ Custom database tables
- ✅ Existing tables (additional columns)
- ✅ File system
- ✅ External APIs
- ✅ Cache/Redis
- ✅ Computed on-the-fly (no storage)
Manual Save and Load
Extension attributes require manual implementation of save and load logic using plugins.
Example: Load Extension Attribute
<?php
namespace Vendor\Module\Plugin;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\Data\ProductExtensionFactory;
use Vendor\Module\Api\RelatedBlogPostRepositoryInterface;
class ProductRepositoryPlugin
{
private $extensionFactory;
private $blogPostRepository;
public function __construct(
ProductExtensionFactory $extensionFactory,
RelatedBlogPostRepositoryInterface $blogPostRepository
) {
$this->extensionFactory = $extensionFactory;
$this->blogPostRepository = $blogPostRepository;
}
public function afterGet(
\Magento\Catalog\Api\ProductRepositoryInterface $subject,
ProductInterface $product
) {
$extensionAttributes = $product->getExtensionAttributes();
if ($extensionAttributes === null) {
$extensionAttributes = $this->extensionFactory->create();
}
// Load extension attribute data from custom source
$blogPosts = $this->blogPostRepository->getByProductId($product->getId());
$extensionAttributes->setRelatedBlogPosts($blogPosts);
$product->setExtensionAttributes($extensionAttributes);
return $product;
}
}
Creating Extension Attributes
Extension attributes require an entry in etc/extension_attributes.xml.
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Catalog\Api\Data\ProductInterface">
<!-- Simple scalar attribute -->
<attribute code="custom_flag" type="string" />
<!-- Array of objects -->
<attribute code="related_blog_posts" type="Vendor\Module\Api\Data\BlogPostInterface[]" />
<!-- Single object -->
<attribute code="shipping_estimate" type="Vendor\Module\Api\Data\ShippingEstimateInterface" />
</extension_attributes>
</config>
WebAPI Availability
Extension attributes are automatically available in WebAPI responses as Extension Attributes.
API Response Example:
{
"id": 123,
"sku": "product-sku",
"name": "Product Name",
"custom_attributes": [
{
"attribute_code": "warranty_period",
"value": "12"
}
],
"extension_attributes": {
"custom_flag": "some_value",
"related_blog_posts": [
{
"id": 1,
"title": "Blog Post Title"
}
]
}
}
custom_attributes, extension attributes appear as extension_attributes.
Use for Custom Entities
- Create your data interface extending
AbstractExtensibleObject - Define extension attributes in XML
- Implement load/save logic in plugins
- No complex EAV setup required
Decision Matrix: When to Use Each Type
Use EAV Attributes When:
- ✅ Extending products, categories, or customers
- ✅ Adding simple scalar values (text, number, date)
- ✅ Need automatic save/load
- ✅ Need scope support (website/store view)
- ✅ Want automatic grid/form display
- ✅ Need filtering/searching in admin
- ✅ Implementing behavior changes based on value
Use Extension Attributes When:
- ✅ Need complex data types (objects, arrays)
- ✅ Extending non-EAV entities (orders, quotes)
- ✅ Data from external sources (APIs, files)
- ✅ Need custom storage control
- ✅ Creating custom entities
- ✅ Computed/derived data (no persistence)
- ✅ WebAPI-focused integration
Real-World Scenarios
Scenario 1: Product Warranty (Use EAV)
Requirement: Add warranty period to products, different per store view, filterable in admin.
Solution: EAV attribute
- ✅ Simple integer value
- ✅ Need scope support
- ✅ Want admin grid filtering
- ✅ Automatic persistence
Scenario 2: Shipping Estimates (Use Extension)
Requirement: Add real-time shipping estimates from external API to cart items.
Solution: Extension attribute
- ✅ Complex object (carrier, cost, time)
- ✅ Computed from external API
- ✅ No database persistence needed
- ✅ WebAPI integration
Scenario 3: Custom Order Notes (Use Extension)
Requirement: Store structured internal notes about orders.
Solution: Extension attribute
- ✅ Orders don't use EAV
- ✅ Complex structure (author, timestamp, note)
- ✅ Custom table for storage
- ✅ Manual save/load control
Exam Tips
Key Points to Remember
- Attributes are functional - change behavior, not just data
- Two primary types: EAV and Extension
- EAV applied to: AbstractEntity resource models (products, categories, customers)
- Extension applied to: AbstractExtensibleObject or AbstractExtensibleModel
- EAV storage: *_entity_varchar, *_entity_int, *_entity_decimal, *_entity_text, *_entity_datetime
- Extension storage: Developer decides (custom tables, files, APIs, computed)
- EAV save/load: Automatic in AbstractEntity
- Extension save/load: Manual implementation via plugins
- EAV creation: DataPatch with EavSetup
- Extension creation: etc/extension_attributes.xml
- WebAPI: EAV = custom_attributes, Extension = extension_attributes
- Scope: EAV has built-in support, Extension requires manual implementation
- Grid/Form: EAV has built-in support, Extension requires custom work
- Custom entities: EAV very difficult, Extension easy
- Data types: EAV only scalar, Extension supports objects/arrays