Edit in GitHubLog an issue

EAV and extension attributes

There are two types of attributes you can use to extend Adobe Commerce and Magento Open Source functionality:

  • Custom and Entity-Attribute-Value (EAV) attributes—Custom attributes are those added on behalf of a merchant. For example, a merchant might need to add attributes to describe products, such as shape or volume. A merchant can add these attributes in the Admin panel. See the merchant documentation for information about managing custom attributes.

    Custom attributes are a subset of EAV attributes. Objects that use EAV attributes typically store values in several MySQL tables. The Customer and Catalog modules are the primary models that use EAV attributes. Other modules, such as ConfigurableProduct, GiftMessage, and Tax, use the EAV functionality for Catalog.

  • Extension attributes. Extension attributes are new in Adobe Commerce and Magento Open Source. They are used to extend functionality and often use more complex data types than custom attributes. These attributes do not appear in the Admin.

Custom attributes#

CustomAttributesDataInterface defines the methods that are called to get and set custom attributes, including getCustomAttributes().

A module has a set of built-in attributes that are always available. The Catalog module has several attributes that are defined as EAV attributes, but are treated as built-in attributes. These attributes include:

  • attribute_set_id
  • created_at
  • group_price
  • media_gallery
  • name
  • price
  • sku
  • status
  • store_id
  • tier_price
  • type_id
  • updated_at
  • visibility
  • weight

In this case, when getCustomAttributes() is called, the system returns only custom attributes that are not in this list.

The Customer module provides a system option for its attributes. As a result, the getCustomAttributes() method only returns those EAV attributes that are not defined as system attributes. If you create custom attributes programmatically, set the system option to 'false' if you want to include the attribute in the custom_attributes array.

Adding Customer EAV attribute for backend only#

Customer EAV attributes are created using a data patches.

Copied to your clipboard
1<?php
2/**
3 * Copyright © Magento, Inc. All rights reserved.
4 * See COPYING.txt for license details.
5 */
6
7namespace Magento\Customer\Setup\Patch\Data;
8
9use Magento\Customer\Model\Customer;
10use Magento\Customer\Setup\CustomerSetupFactory;
11use Magento\Framework\App\ResourceConnection;
12use Magento\Framework\Setup\ModuleDataSetupInterface;
13use Magento\Framework\Setup\Patch\DataPatchInterface;
14use Magento\Framework\Setup\Patch\PatchVersionInterface;
15
16/**
17 * Class add customer example attribute to customer
18 */
19class AddCustomerExampleAttribute implements DataPatchInterface
20{
21 /**
22 * @var ModuleDataSetupInterface
23 */
24 private $moduleDataSetup;
25
26 /**
27 * @var CustomerSetupFactory
28 */
29 private $customerSetupFactory;
30
31 /**
32 * @param ModuleDataSetupInterface $moduleDataSetup
33 * @param CustomerSetupFactory $customerSetupFactory
34 */
35 public function __construct(
36 ModuleDataSetupInterface $moduleDataSetup,
37 CustomerSetupFactory $customerSetupFactory
38 ) {
39 $this->moduleDataSetup = $moduleDataSetup;
40 $this->customerSetupFactory = $customerSetupFactory;
41 }
42
43 /**
44 * @inheritdoc
45 */
46 public function apply()
47 {
48 $customerSetup = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]);
49 $customerSetup->addAttribute(Customer::ENTITY, 'attribute_code', [
50 // Attribute options (list of options can be found below)
51 ]);
52 }
53
54 /**
55 * @inheritdoc
56 */
57 public static function getDependencies()
58 {
59 return [
60 UpdateIdentifierCustomerAttributesVisibility::class,
61 ];
62 }
63
64 /**
65 * @inheritdoc
66 */
67 public function getAliases()
68 {
69 return [];
70 }
71}

Extension attributes#

Use ExtensibleDataInterface to implement extension attributes. In your code, you must define getExtensionAttributes() and setExtensionAttributes(*ExtensionInterface param).

public function getExtensionAttributes();

Most likely, you will want to extend interfaces defined in the Api/Data directory of a module.

Declare extension attributes#

You must create a <Module>/etc/extension_attributes.xml file to define a module's extension attributes:

Copied to your clipboard
1<config>
2 <extension_attributes for="Path\To\Interface">
3 <attribute code="name_of_attribute" type="datatype">
4 <resources>
5 <resource ref="permission"/>
6 </resources>
7 <join reference_table="" reference_field="" join_on_field="">
8 <field>fieldname</field>
9 </join>
10 </attribute>
11 </extension_attributes>
12</config>

where:

KeywordDescriptionExample
forThe fully-qualified type name with the namespace that processes the extensions. The value must be a type that implements ExtensibleDataInterface. The interface can be in a different module.Magento\Quote\Api\Data\TotalsInterface
codeThe name of the attribute. The attribute name should be in snake case (the first letter in each word should be in lowercase, with each word separated by an underscore).gift_cards_amount_used
typeThe data type. This can be a simple data type, such as string or integer, or complex type, such as an interface.float
Magento\CatalogInventory\Api\Data\StockItemInterface
refOptional. Restricts access to the extension attribute to users with the specified permission.Magento_CatalogInventory::cataloginventory
reference_tableThe table involved in a join operation. See Searching extension attributes for details.admin_user
reference_fieldColumn in the reference_table.user_id
join_on_fieldThe column of the table associated with the interface specified in the for keyword that will be used in the join operation.store_id
fieldOne or more fields present in the interface specified in the type keyword.
You can specify the column="" keyword to define the column in the reference_table to use. The field value specifies the property on the interface which should be set.
<field>firstname</field>
<field>lastname</field>
<field>email</field>

<field column="customer_group_code">code</field>

Searching extension attributes#

The system uses a join directive to add external attributes to a collection and to make the collection filterable. The join element in the extension_attributes.xml file defines which object fields and the database table/column to use as the source of a search.

In the following example, an attribute named stock_item of type Magento\CatalogInventory\Api\Data\StockItemInterface is being added to the Magento\Catalog\Api\Data\ProductInterface.

Copied to your clipboard
1<extension_attributes for="Magento\Catalog\Api\Data\ProductInterface">
2 <attribute code="stock_item" type="Magento\CatalogInventory\Api\Data\StockItemInterface">
3 <join reference_table="cataloginventory_stock_item" reference_field="product_id" join_on_field="entity_id">
4 <field>qty</field>
5 </join>
6 </attribute>
7</extension_attributes>

When getList() is called, it returns a list of ProductInterfaces. When it does this, the code populates the stock_item with a joined operation in which the StockItemInterface’s qty property comes from the cataloginventory_stock_item table where the Product's entity_Id is joined with the cataloginventory_stock_item.product_id column.

When you add search extension attributes, you must consider that this can cause ambiguity in the selection of fields in the resulting SQL query when using REST APIs. In these cases, the REST call must explicitly specify both the table name and field to use for selecting.

For example, the following configuration may introduce ambiguity when getting orders via REST API. The configuration constructs a query like SELECT .... FROM sales_order AS main_table LEFT JOIN sales_order. This creates an ambiguity for all columns from the sales_order table in that MySQL cannot determine if it should take them from the main_table or from the sales_order from the JOIN clause.

Copied to your clipboard
1<config>
2 <extension_attributes for="Magento\Sales\Api\Data\OrderInterface">
3 <attribute code="field1" type="int">
4 <join reference_table="sales_order" join_on_field="entity_id" reference_field="entity_id">
5 <field>field1</field>
6 </join>
7 </attribute>
8 </extension_attributes>
9</config>

REST API Endpoint:

GET http://<host>/rest/default/V1/orders

Payload:

Copied to your clipboard
1searchCriteria[filter_groups][0][filters][0]
2[field]=main_table.created_at&searchCriteria
3[filter_groups][0][filters][0][value]=2021-09-14%2000:00:00
4&searchCriteria[filter_groups][0][filters][0]
5[conditionType]=from
6&searchCriteria[filter_groups][1][filters][0]
7[field]=main_table.created_at
8&searchCriteria[filter_groups][1][filters][0]
9[value]=2021-09-14%2023:59:59
10&searchCriteria[filter_groups][1][filters][0]
11[conditionType]=to
12&searchCriteria[pageSize]=10
13&searchCriteria[currentPage]=86

Extension attribute authentication#

Individual fields that are defined as extension attributes can be restricted, based on existing permissions. This feature allows extension developers to restrict access to data. See Web API authentication overview for general information about authentication in Magento.

The following code sample defines stock_item as an extension attribute of the CatalogInventory module. CatalogInventory is treated as a "third-party extension". Access to the inventory data is restricted because the quantity of in-stock item may be competitive information.

Copied to your clipboard
1<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
2 <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface">
3 <attribute code="stock_item" type="Magento\CatalogInventory\Api\Data\StockItemInterface">
4 <resources>
5 <resource ref="Magento_CatalogInventory::cataloginventory"/>
6 </resources>
7 </attribute>
8 </extension_attributes>
9</config>

In this example, the stock_item attribute is restricted to only the users who have the Magento_CatalogInventory::cataloginventory permission. As a result, an anonymous or unauthenticated user issuing a GET <host>/rest/<store_code>/V1/products/<sku> request will receive product information similar to the following:

Copied to your clipboard
1 {
2 "sku": "tshirt1",
3 "price": "20.00",
4 "description": "New JSmith design",
5 "extension_attributes": {
6 "logo size": "small"
7 },
8 "custom_attributes": {
9 "artist": "James Smith"
10 }
11 }

However, an authenticated user with the permission Magento_CatalogInventory::cataloginventory receives the additional stock_item field:

Copied to your clipboard
1 {
2 "sku": "tshirt1",
3 "price": "20.00",
4 "description": "New JSmith design",
5 "extension_attributes": {
6 "logo size": "small",
7 "stock_item" : {
8 "status" : "in_stock"
9 "quantity": 70
10 }
11 },
12 "custom_attributes": {
13 "artist": "James Smith"
14 }
15 }

This only works for extension attributes (those attributes defined in an extension_attributes.xml file). There are no permission restrictions on the rest of the returned data. For example, there is no way to restrict custom_attributes.

Extension interfaces#

An ExtensionInterface will be empty if no extension attributes have been added. In the following example—in an unmodified installation—CustomerExtensionInterface will be generated, but will be empty:

Copied to your clipboard
1use Magento\Framework\Api\ExtensionAttributesInterface;
2interface CustomerExtensionInterface extends ExtensionAttributesInterface
3{
4}

However, if an extension similar to the following has been defined, the interface will not be empty:

Copied to your clipboard
1<extension_attributes for="Magento\Customer\Api\Data\CustomerInterface">
2 <attribute code="attributeName" type="Magento\Some\Type[]" />
3</extension_attributes>

Troubleshoot EAV attributes#

If you have issues when using setup:upgrade, verify __construct uses the method EavSetupFactory not EavSetup. You should not directly inject EavSetup in extension code. Check your custom code and purchased modules and extensions to verify. After changing the methods, you should be able to properly deploy.

Add product EAV attribute options reference#

The following table is a reference for the Magento\Eav\Setup\EavSetup::addAttribute method. It contains the available options when creating a product attribute, listing each option's key, description, and the default value (where applicable).

KeyDescriptionDefault Value
apply_toCatalog EAV Attribute - defines which product types the attribute can be applied to
attribute_modelEAV Attribute attribute_model
attribute_setName of the attribute set the new attribute will be assigned to. Works in combination with group or empty user_defined
backendEAV Attribute backend_model
comparableCatalog EAV Attribute - defines if attribute can be used when comparing products0
defaultEAV Attribute default_value
filterable_in_searchCatalog EAV Attribute is_filterable_in_search - defines if attribute can be used to filter search results0
filterableCatalog EAV Attribute is_filterable - defines if attribute can be used to filter on navigation0
frontend_classEAV Attribute frontend_class
frontendEAV Attribute frontend_model
globalCatalog EAV Attribute is_global field1
groupAttribute group name or ID
input_rendererCatalog EAV Attribute frontend_input_renderer
inputEAV Attribute frontend_inputtext
is_filterable_in_gridCatalog EAV Attribute - defines if attribute can be used to filter on product grid in Admin0
is_html_allowed_on_frontCatalog EAV Attribute - defines if HTML needs to be escaped on the frontend0
is_used_in_gridCatalog EAV Attribute - defines if attribute can be used on the product grid in Admin0
is_visible_in_gridCatalog EAV Attribute is_visible_in_grid - defines if attribute will be visible on the product grid in Admin0
labelEAV Attribute frontend_label
noteEAV Attribute note
optionEAV Attribute Option values
positionCatalog EAV Attribute position0
requiredEAV Attribute is_required1
searchableCatalog EAV Attribute is_searchable0
sort_orderEAV Entity Attribute sort_order
sourceEAV Attribute source_model
systemDeclares the attribute as a system attribute.1
tableEAV Attribute backend_table
typeEAV Attribute backend_typevarchar
uniqueEAV Attribute is_unique0
used_for_promo_rulesCatalog EAV Attribute is_used_for_promo_rules0
used_for_sort_byCatalog EAV Attribute used_for_sort_by0
used_in_product_listingCatalog EAV Attribute used_in_product_listing0
user_definedEAV Attribute is_user_defined0
visible_in_advanced_searchCatalog EAV Attribute is_visible_in_advanced_search - defines if attribute will appear on the Advanced Search form0
visible_on_frontCatalog EAV Attribute is_visible_on_front - defines attribute visibility on frontend0
visibleCatalog EAV Attribute is_visible - defines visibility in Admin, won't be available for changing a value in the admin interface if set to 01
wysiwyg_enabledCatalog EAV Attribute is_wysiwyg_enabled - used for enabling wysiwyg editor for an attribute. Works for textarea only0
Was this helpful?
  • Privacy
  • Terms of Use
  • Do not sell my personal information
  • AdChoices
Copyright © 2022 Adobe. All rights reserved.