Table of content

Magento 2 Certified Professional Developer Guide


Section 5: Using the Entity-Attribute-Value (EAV) Model

5.1 Demonstrate ability to use EAV model concepts

Describe the EAV hierarchy structure

EAV (Entity-attribute-value) is a model for storing entity attribute values ​​in a certain storage place. For storage, Magento 2 supports MySQL-compatible databases (like MySQL, MySQL NDB Cluster, MariaDB, Percona, and others).

The table of the classic EAV model has 3 columns:

  1. entity (object to which the attribute value must be set)
  2. attribute
  3. value

In the Flat model, attribute values ​​are stored in the same table as the entities; a separate column is created for each attribute in the table.

In the EAV model, attribute values ​​are stored in a separate table. A separate column is not created for each attribute, and a new row is created for each attribute value of an entity in the EAV table.

How EAV data storage works in Magento

Differences between a classic EAV model and the one used in Magento
  1. A backend type (varchar, int, text …) is assigned for each attribute
  2. Each EAV entities type have a separate table. EAV entities types are stored in eav_entity_type table. The names of the tables, where the entities are stored, are located in entity_table column.
  3. System EAV entities are stored in eav_entity table
  4. Attributes, that have backend type as static, are stored in the same table as entities. These attributes have global scope.
  5. Each backend type of each entity type has its own table, in which attribute values are stored. The name of this table is crafted according to the template {entity_table} _ {backend_type}, where entity_table is the name of the entity table and backend_type is the backend type of the attribute. These tables include the following columns: value_id (int), attribute_id (int), store_id ** (int), entity_id * (int), value (depending on the backend type).

To get a better understanding of the connections, study this scheme:

Magento 2 Certified Professional Developer Guide Screenshot 23

To get / record attribute value, you need:

  1. store_id**
  2. entity_id*
  3. entity_table или entity_type_id
  4. attribute_id

If entity_table is unknown, but entity_type_id is known, then entity_table can be obtained from the eav_entity_type table.

Magento receives entity attribute values as one large SQL query, which is generated by the following algorithm:

  1. Get all attribute tables for a specific entity_type
  2. For each table, do the following:
    • a select subquery is created from the current table, which requests value and attribute_id
    • the condition is added that entity_id = ID of the requested entity *
    • a condition is added for each scope that store_id IN ($ scope-> getValue ()) **
    • sorted by store_id in a descending order
  3. UNION ALL of all subqueries is performed.

* the field is not necessarily called entity_id. Magento uses $metadata->getLinkField() to get the field name.

** the field is not necessarily called store_id. Magento uses $scope->getIdentifier() to get the field name.

What happens when a new attribute is added to the system

When a new attribute is added, new records are created in the database. Similar records are created for each attribute type.

Let’s consider some standard attribute types.

Text Field

Let’s examine how to create a new attribute of the Text Field type.

  1. A new record in eav_attribute table is made
attribute_identity_type_idattribute_code
1544test_code

2.  One entry per store view is created in the eav_attribute_label table with the Label attribute.

attribute_label_idattribute_idstore_idvalue
171541Test label

3.  A new record in the catalog_eav_attribute table is created

attribute_idfrontend_input_rendereris_global
154NULL1
Dropdown

Magento 2 Certified Professional Developer Guide Screenshot 24

Differences compared to Field:

  • eav_attribute.frontend_input = “select”
  • eav_attribute.source_model = “Magento\Eav\Model\Entity\Attribute\Source\Table”
  • eav_attribute.backend_type = “int”
  • eav_attribute.default_value = eav_attribute_option.option_id by default
  • Lines are added in eav_attribute_option, one for each value
option_idattribute_idsort_order
2101551
2111552
2121553
  • Lines are added in eav_attribute_option_value
value_idoption_idstore_idvalue
20821102
21021203
2052101One
2072111Two
2092121Three
20621001
Price

Differences compared to Text Field:

  • eav_attribute.frontend_input = “price”
  • eav_attribute.backend_model = “Magento\Catalog\Model\Product\Attribute\Backend\Price”
  • eav_attribute.backend_type = “decimal”
Media image

Differences compared to Text Field:

  • eav_attribute.frontend_input = “media_image”
Text swatch

Magento 2 Certified Professional Developer Guide Screenshot 25

Differences compared to Dropdown:

  • catalog_eav_attribute.additional_data look similarly {“swatch_input_type”:”text”,”update_product_preview_image”:”0″,”use_product_image_for_swatch”:0}
  • Lines into eav_attribute_option_swatch are added
swatch_idoption_idstore_idtypevalue
1213001
6215103
2213101
4214102
3214002
5215003

How are attributes presented in the admin?

Attributes consist of a name (Label) + field, the value of which the administrator can change.

The following attribute properties affect the display:

  • frontend_model – a class that describes the field display in the frontend section of a site. Inherited from Magento \ Eav \ Model \ Entity \ Attribute \ Frontend \ AbstractFrontend and overrides the getValue method to change the displayed attribute values
  • frontend_input – the form element that is displayed in the admin section of the site
  • frontend_label – the name of the attribute, displayed in the admin section of the site. It is also displayed in the site frontend, unless otherwise specified in the eav_attribute_label table (in the attribute settings it is changed in the “Manage Labels” tab)
  • frontend_class – used to validate the attribute value in the admin section of the site. In the attribute settings, the property is called Input Validation for Store Owner. For e-mail validation, the frontend_class property is set to “validate-email”.

Magento 2 Certified Professional Developer Guide Screenshot 26

Magento 2 Certified Professional Developer Guide Screenshot 27

Magento has the following default attribute types:

Text Field

Has the form of text input.

Magento 2 Certified Professional Developer Guide Screenshot 28

Text Area

Has the form of a many-line input field. A WYSIWYG editor can be enabled for it in the attribute settings.

Magento 2 Certified Professional Developer Guide Screenshot 29

Date

Has the form of a text field for data input and a drop-down calendar.

Magento 2 Certified Professional Developer Guide Screenshot 30

Yes/No

Has the form of a switcher with two entities: Yes or No.

Magento 2 Certified Professional Developer Guide Screenshot 31

Multiple Select

Has the form of a list that offers to select several values, or no value at all.

Magento 2 Certified Professional Developer Guide Screenshot 32

Dropdown

Has the form of a drop-down list that offers to select only one value.

Magento 2 Certified Professional Developer Guide Screenshot 33

Price

Has the form of a text field with a currency symbol.

Magento 2 Certified Professional Developer Guide Screenshot 34

Media Image

Media Image is different from any other fields, for it has no field. Instead, an attribute of Media Image type adds role to the product image and video.

Magento 2 Certified Professional Developer Guide Screenshot 35Magento 2 Certified Professional Developer Guide Screenshot 36

Fixed Product Tax

Allows to modify taxes for countries and its states. Has the form of a table with a country/state and corresponding tax. The type is added by the Magento_Weee module, where WEE stands for Waste Electrical and Electronic Equipment Directive.

Magento 2 Certified Professional Developer Guide Screenshot 37

Visual Swatch

Visual Swatch is provided for the administrator, the same as Dropdown. The user sees it as a button, filled with color, or containing a picture. This field can be used in Configurable products, for instance, for the color selection.

Magento 2 Certified Professional Developer Guide Screenshot 38Magento 2 Certified Professional Developer Guide Screenshot 39

Text Swatch

Is provided similarly to Visual Swatch, only the button content is in text format.

Magento 2 Certified Professional Developer Guide Screenshot 40

What is the role of attribute sets and attribute groups?

Attribute set are applied to display different attributes during various product types editing (eg., shoes and clothes). For example, we have shoe_size and clothing_size attributes, and we need to display the first one for shoes, and the second – for clothes. Attribute set allows to hide the unnecessary attributes, display the needed ones, modify the sorting and group. Groups simplify the process of filling product information by the administrator, but have no effect on product loading / storing logic.

Below is a screenshot, where Design and Schedule Design Update are attribute groups, and the nested elements are attributes.

Attributes in attribute set settings:

Magento 2 Certified Professional Developer Guide Screenshot 41

Attributes in the product:

Magento 2 Certified Professional Developer Guide Screenshot 42

Which additional options do you have when saving EAV entities?

The EAV entity modification page offer the following capabilities:

  • Default attribute value. Allows to set the value that will be inserted into the attribute field if it is not filled in. This simplifies the process of adding and modifying the entities. These are the potential default attribute values for the product:
    • Text Field – any one-line text
    • Text Area – any multi-line text
    • Date – any date
    • Yes/No – yes or no
    • Multiple Select – any number of options
    • Dropdown – one option
    • Price – no default value
    • Media image – no default value
    • Visual Swatch – one option
    • Text Swatch – one option
    • Fixed Product Tax – no default value
  • Scope selection. Scope allows to set different attribute values for different website / store / view. Below is a list of the possible attribute scope for the product:
    • Text Field – store view / website / global
    • Text Area – store view / website / global
    • Date – store view / website / global
    • Yes/No – store view / website / global
    • Multiple Select – store view / website / global
    • Dropdown – store view / website / global
    • Price – website / global (configured in Stores – Configuration – Catalog – Catalog – Price – Catalog Price Scope)
    • Media image – store view / website / global
    • Visual Swatch – store view / website / global
    • Text Swatch – store view / website / global
    • Fixed Product Tax – global
  • Attribute set selection (products only). Allows to regroup or hide the attributes that do not suit the current product type.

Before saving an EAV entity at the client side, we have the following features:

  • Prohibition to save entities, if there are empty attribute fields with the is_required = 1 feature. It allows to define what attributes of the entity are required to be filled in.
  • Validation of the attribute fields values by the algorithm, set in frontend_class. The following frontend classes are supported by default it Magento:
    • validate-number: Decimal Number
    • validate-digits: Integer Number
    • validate-email: Email
    • validate-url: URL
    • validate-alpha: Letters
    • validate-alphanum: Letters (a-z, A-Z) or Numbers (0-9)

Before saving an EAV entity at the server side, we have the following features:

  • Check attribute fields with is_required = 1 for fullness. Magento checks the required fields on both the client and server sides.
  • Uniqueness check of the attribute fields with is_unique = 1.
  • Perform operations in backend_model
    • Validation (validate method). Allows to realize additional server check before saving
    • Operation before saving (beforeSave method)
    • Operation after saving ( afterSave method)

Module catalog has an additional catalog_eav_attribute table for attributes, where the following parameters are stored:

  • Frontend Input Renderer
  • Is Global
  • Is Visible
  • Is Searchable
  • Is Filterable
  • Is Comparable
  • Is Visible On Front
  • Is HTML Allowed On Front
  • Is Used For Price Rules
  • Is Filterable In Search
  • Is Used In Product Listing
  • Is Used For Sorting
  • Is Visible In Advanced Search
  • Is WYSIWYG Enabled
  • Is Used For Promo Rules
  • Is Required In Admin Store
  • Is Used in Grid
  • Is Visible in Grid
  • Is Filterable in Grid

These parameters allow to perform a more sophisticated attribute configuration.

How do you create customizations based on changes to attribute values?

To customize an attribute, modify the following attribute features:

  • backend_model
  • source_model
  • attribute_model
  • frontend_model
Attribute Model

The model allows to perform a more sophisticated attribute setting. By default, Magento\Eav\Model\Entity\Attribute is used, and a model, different from the default one, is rarely applied.

Backend Model

The model is used for processing and validating the attribute values.

By default, Magento\Eav\Model\Entity\Attribute\Backend\DefaultBackend is used.

It allows to define:

  • validate
  • afterLoad
  • beforeSave
  • afterSave
  • beforeDelete
  • afterDelete
  • and other

Example:

class TestBackend extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
{
    public function validate($object)
    {
    	$attribute_code = $this->getAttribute()->getAttributeCode();
        $value = $object->getData($attribute_code);

        if ($value == 'test') {
        	throw new \Magento\Framework\Exception\LocalizedException(__("Value can't be test"));
        }

        return true;
    }
}
Source Model

The model is used for providing the list of the attribute values.

By default, Magento\Eav\Model\Entity\Attribute\Source\Config is used.

Example:

class TestSource extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
{
    public function getAllOptions()
    {
        if (!$this->_options) {
            $this->_options = [
                ['label' => __('Label 1'), 'value' => 'value 1'],
                ['label' => __('Label 2'), 'value' => 'value 2'],
                ['label' => __('Label 3'), 'value' => 'value 3'],
                ['label' => __('Label 4'), 'value' => 'value 4']
            ];
        }
        return $this->_options;
    }
}
Frontend Model

Frontend model is used for displaying frontend part of the website.

By default, Magento\Eav\Model\Entity\Attribute\Frontend\DefaultFrontend is applied.

Example:

class TestFrontend extends \Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend
{
    public function getValue(\Magento\Framework\DataObject $object)
    {
        $attribute_code = $this->getAttribute()->getAttributeCode();
        $value = $object->getData($attribute_code);
        return nl2br(htmlspecialchars($value));
    }
}

Describe the key differences between EAV and flat table collections

For a developer, there is no big difference between EAV and Flat. Models, resource models and collections are created similarly.

Let us examine how the classes for EAV (City) and Flat (Country) are created.

Collections

EAV

<?php
namespace Belvg\Geo\Model\ResourceModel\City;

class Collection extends \Magento\Eav\Model\Entity\Collection\AbstractCollection
{
    protected function _construct()
    {
        $this->_init(
            'Belvg\Geo\Model\City',
            'Belvg\Geo\Model\ResourceModel\City'
        );
    }
}

FLAT

<?php
namespace Belvg\Geo\Model\ResourceModel\Country;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    protected function _construct()
    {
        $this->_init(
            'Belvg\Geo\Model\Country',
            'Belvg\Geo\Model\ResourceModel\Country'
        );
    }
}
Resource model

EAV

<?php
namespace Belvg\Geo\Model\ResourceModel;

class City extends \Magento\Eav\Model\Entity\AbstractEntity
{
    public function getEntityType()
    {
        if (empty($this->_type)) {
            $this->setType(\Belvg\Geo\Model\City::ENTITY);
        }
        return parent::getEntityType();
    }
}

FLAT

<?php
namespace Belvg\Geo\Model\ResourceModel;

class Country extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    protected function _construct()
    {
        $this->_init(
            'belvg_geo_country',
            'entity_id'
        );
    }
}
Models

EAV

<?php
namespace Belvg\Geo\Model;

class City extends \Magento\Framework\Model\AbstractModel
{
    const ENTITY = 'belvg_geo_city';

    protected function _construct()
    {
        $this->_init('Belvg\Geo\Model\ResourceModel\City');
    }
}

FLAT

<?php
namespace Belvg\Geo\Model;

class Country extends \Magento\Framework\Model\AbstractModel
{
    protected function _construct()
    {
        $this->_init('Belvg\Geo\Model\ResourceModel\Country');
    }
}
Difference between EAV classes and FLAT

Additionally, the following methods, that contain the attribute as its code or its object, are added into EAV collections:

  • addAttributeToSelect converts attribute into its code and calls addFieldToSelect
  • addAttributeToFilter converts attribute into its code and calls addFieldToFilter
  • addAttributeToSort converts attribute into its code and calls addOrder

Additionally, in EAV resource models, the methods for working with attributes are added and methods load, save, delete are overridden.

EAV utilizes the following classes for working with attributes:

  • Magento\Eav\Model\ResourceModel\CreateHandler – to create values in new entities
  • Magento\Eav\Model\ResourceModel\UpdateHandler – to modify / delete / add values into the existing entities
  • Magento\Eav\Model\ResourceModel\ReadHandler – to get the values

The key difference between EAV and Flat lies in data storage.

The configuration settings in the admin panel have Use Flat Catalog Category and Use Flat Catalog Product options. The settings allow to edit the sources of the uploaded products and categories, changing them from EAV tables for FLAT index tables.

Product attribute gets to the flat table in case it complies to at least one condition:

  • backend_type is set as static
  • the field filter is enabled
  • the attribute is used in the product list
  • the attribute is used for sorting

Product collection is a Magento\Catalog\Model\ResourceModel\Product\Collection class. In this class, many methods look the following way:

if ($this->isEnabledFlat()) {
...
} else {
...
}

Therefore, if Flat is enabled, one action is performed, but in case it is disabled, then another action is triggered.

The situation is different with categories. Magento\Catalog\Model\Category model is initialized the following way:

 protected function _construct()
    {
        // If Flat Index enabled then use it but only on frontend
        if ($this->flatState->isAvailable()) {
            $this->_init(\Magento\Catalog\Model\ResourceModel\Category\Flat::class);
            $this->_useFlatResource = true;
        } else {
            $this->_init(\Magento\Catalog\Model\ResourceModel\Category::class);
        }
    }

Therefore, different resource models are used.

Collections also divided into two classes, unlike the products:

  • Magento\Catalog\Model\ResourceModel\Category\Collection
  • Magento\Catalog\Model\ResourceModel\Category\Flat\Collection

In which situations would you use EAV for a new entity

Using EAV for a new entity is advisable in case at least one of the following conditions is true:

  1. There is a scope.
  2. Admins and modules have the ability to add attributes into an entity or modify attributes backend type.
  3. Potentially, the number of columns in Flat model can exceed 1017.
  4. Potentially, the required amount of indexes, like INDEX in Flat model, can exceed 64 or reach the amount when the entities’ adding / modifying / deletion will be slow.

What are the pros and cons of EAV architecture?

Advantages of EAV over Flat
  1. The implementation of SCOPE in the Flat model stores a lot of unnecessary information. For example, if you want to redefine one attribute in another scope, then both EAV and Flat will create one line each. But in EAV, the number of columns is always fixed, while in Flat it can reach 1000. Additionally, there is a problem when the value is inherited from the parent scope. You can mark such values ​​as NULL, but then you must prevent the attributes from being NULL if they are not inherited.
  2. Quickly add a new attribute. Adding a new attribute does not change the EAV table in any way. In Flat, you need to add a new column. The ALTER TABLE operation is also slow. This is especially noticeable in large tables. *
  3. Change the backend type attribute faster. To change the attribute type in EAV, you need to move the this attribute data from one table to another. For Flat, you need to perform ALTER TABLE. *
  4. EAV allows to separate attribute values ​​from entity field values.
  5. The following InnoDB restrictions on the table restrict Flat:
    • The table may contain no more than 1017 columns
    • A table can contain a maximum of 64 indexes of type INDEX
Disadvantages of EAV over Flat
  1. Getting entity attribute values ​​in EAV is slower than in Flat **
  2. Search by attribute value in EAV is slower than in Flat **
  3. In Flat, you can create an index on several attributes to speed up the search **

* As for EAV, when adding / changing an attribute type, ALTER TABLE is performed if the attribute’s backend type is static

** To speed up operations, some attributes can be set the backend type as static and, if necessary, create indexes on the column with the attribute in the database, but then the visibility of the attribute will only be global. Another option is to use a flat table as an index if the data is allowed not to be up to date.

5.2 Demonstrate ability to use EAV entity load and save

The Magento\Framework\EntityManager\EntityManager class was introduced in Magento 2.1 for loading, saving, checking for existence, deleting EAV and Flat objects (now it is considered deprecated).

To work via EntityManager, you must provide information about the entity interface in di.xml for MetadataPool and for HydratorPool.

<type name="Magento\Framework\EntityManager\MetadataPool">
    <arguments>
        <argument name="metadata" xsi:type="array">
            <item name="MyVendor\MyModule\Api\Data\MyEntityInterface" xsi:type="array">
                <item name="entityTableName" xsi:type="string">myvendor_mymodule_myentity_entity</item>
                <item name="eavEntityType" xsi:type="string">myvendor_mymodule_myentity</item>
                <item name="identifierField" xsi:type="string">entity_id</item>
                <item name="entityContext" xsi:type="array">
                    <item name="store" xsi:type="string">Magento\Store\Model\StoreScopeProvider</item>
                </item>
            </item>
        </argument>
    </arguments>
</type>

<type name="Magento\Framework\EntityManager\HydratorPool">
    <arguments>
        <argument name="hydrators" xsi:type="array">
            <item name="MyVendor\MyModule\Api\Data\MyEntityInterface" xsi:type="string">Magento\Framework\EntityManager\AbstractModelHydrator</item>
        </argument>
    </arguments>
</type>

Magento\Framework\EntityManager\OperationPool class contains operations array that call EntityManager for loading, saving, existence check and object deletion. The operation is performed by execute method.

Default operations:

checkIfExists – Magento\Framework\EntityManager\Operation\CheckIfExists

read – Magento\Framework\EntityManager\Operation\Read

create – Magento\Framework\EntityManager\Operation\Create

update – Magento\Framework\EntityManager\Operation\Update

delete – Magento\Framework\EntityManager\Operation\Delete

By default, CheckIfExists operation checks for the existence of an entry in the main table with a direct SQL query.

By default, Read operation performs three sub-operations:

  • ReadMain
  • ReadAttributes
  • ReadExtensions

By default, Create operation performs three sub-operations:

  • CreateMain
  • CreateAttributes
  • CreateExtensions

By default, Update operation performs three sub-operations:

  • UpdateMain
  • UpdateAttributes
  • UpdateExtensions

By default, Delete operation performs three sub-operations (in reverse order):

  • DeleteExtensions
  • DeleteAttributes
  • DeleteMain

Attribute operations are located in the class Magento \ Framework \ EntityManager \ Operation \ AttributePool.

Extensions operations are located in the class Magento \ Framework \ EntityManager \ Operation \ ExtensionPool.

Using overrides of attributes operations, EAV applies the following classes for operations:

  • Magento\Eav\Model\ResourceModel\CreateHandler
  • Magento\Eav\Model\ResourceModel\UpdateHandler
  • Magento\Eav\Model\ResourceModel\ReadHandler

CreateHandler writes attribute values into the new entities.

UpdateHandler takes a snapshot thanks to ReadSnapshot (which is based on ReadHandler). Then, UpdateHandler:

  • Changes the value, if the attribute is modified relative to Snapshot and the new value is not empty or the attribute allows empty values
  • Deletes, if the attribute is changed relative to Snapshot and the new value is empty and the attribute does not allow empty values
  • Creates, if the attribute is absent in Snapshot and the new value is not empty or the attribute allows empty values

ReadHandler performs reading, using the following algorithm:

  1. Get all attribute tables for a specific entity_type
  2. For each table, the following is performed:
    1. a select subquery is created from the current table, which requests value and attribute_id
    2. the condition is added that entity_id = ID of the requested entity
    3. a condition is added for each scope from the context that store_id IN ($scope-> getValue ())
    4. sorted by store_id in descending order
  3. Performs UNION ALL of all subqueries.
  4. Executes an SQL query
  5. Writes the resulting values are written into the $entityData array.

What happens when an EAV entity has too many attributes?

The advantage of EAV, compared to Flat, is that Flat table in InnoDb can not contain more than 1017 columns. In EAV, the number of attributes is limited by the maximum size of innodb tables.

How does the number of websites/stores affect the EAV load/save process?

The number of websites/stores impacts the entity loading / saving.

Let us consider the influence of websites/stores on attributes saving and loading.

In Magento, scope in EAV is realized due to store_id column in the EAV attribute value tables.

  • store_id = 0, if scope global
  • store_id = ID of the selected Store View, if not global

Attribute values are loaded the following way:

  • store_id IN (STORE_IDS), where STORE_IDS are Store View identificators of the current context.

The context is calculated recursively:

In STORE_IDS array, the identificator of the current scope is added.

In case the current scope has Fallback scope, then an operation is repeated for Fallback.

Example: store_id = 5, fallback is specified as 3, and 3 has fallback as 0. Then STORE_IDS is: [5, 3, 0].

In most cases, the standard scope provider Magento \ Store \ Model \ StoreScopeProvider is used.

It works as follows:

Store_id is specified as the identifier of the current Store View

If current store_id! = 0, then it adds a fallback before as 0

It turns out that number of websites / stores does not directly affect * the upload speed, because when StoreScopeProvider is used during loading, the context contains no more than two store_id, i.e. does not depend on the number of websites / stores.

* the number of websites / stores always indirectly affects the loading of attribute values, as the more rows in the attribute value tables, the slower is the load.

Let us consider the value of store_id while maintaining the attribute value.

Attribute scopeAll Store ViewsCertain Store View
globalstore_id = 0store_id = 0
websitestore_id = 0Entries created / modified for each Store View of the given Website
store viewstore_id = 0store_id = ID Store View

Thus, the attribute saving speed, depending on the number of websites / stores, is affected by the presence of modified attributes from the scope website. The more Store Views are in the Website, the more entries in the database you need to create or modify entries, the slower is the saving.

How would you customize the load and save process for an EAV entity in the situations described here?

To override the operations, add di.xml into the following:

<type name="Magento\Framework\EntityManager\OperationPool">
    <arguments>
        <argument name="operations" xsi:type="array">
            <item name="MyVendor\MyModule\Api\Data\MyEntityInterface" xsi:type="array">
                <item name="checkIsExists" xsi:type="string">MY_NAMESPACE\CheckIsExists</item>
                <item name="read" xsi:type="string">MY_NAMESPACE\Read</item>
                <item name="create" xsi:type="string">MY_NAMESPACE\Create</item>
                <item name="update" xsi:type="string">MY_NAMESPACE\Update</item>
                <item name="delete" xsi:type="string">MY_NAMESPACE\Delete</item>
            </item>
        </argument>
    </arguments>
</type>

You can partially override, for example, a single read operation, then the default operations will be used for the rest of the operations.

We can also override work operations with the attributes for EAV:

<type name="Magento\Framework\EntityManager\Operation\AttributePool">
    <arguments>
        <argument name="extensionActions" xsi:type="array">
            <item name="eav" xsi:type="array">
                <item name="MyVendor\MyModule\Api\Data\MyEntityInterface" xsi:type="array">
                    <item name="read" xsi:type="string">MY_NAMESPACE\ReadHandler</item>
                    <item name="create" xsi:type="string">MY_NAMESPACE\CreateHandler</item>
                    <item name="update" xsi:type="string">MY_NAMESPACE\UpdateHandler</item>
                </item>
            </item>
        </argument>
    </arguments>
</type>

Extensions override:

<type name="Magento\Framework\EntityManager\Operation\ExtensionPool">
    <arguments>
        <argument name="extensionActions" xsi:type="array">
            <item name="MyVendor\MyModule\Api\Data\MyEntityInterface" xsi:type="array">
                <item name="read" xsi:type="array">
                    <item name="myReader" xsi:type="string">MY_NAMESPACE\ReadHandler</item>
                </item>
                <item name="create" xsi:type="array">
                    <item name="myCreator" xsi:type="string">MY_NAMESPACE\CreateHandler</item>
                </item>
                <item name="update" xsi:type="array">
                    <item name="myUpdater" xsi:type="string">MY_NAMESPACE\UpdateHandler</item>
                </item>
            </item>
        </argument>
    </arguments>
</type>

5.3 Demonstrate ability to manage attributes

Describe EAV attributes, including the frontend/source/backend structure

Backend Model performs loading, saving, deletion and validation of the attribute.

Source Model provides a list of values for the attributes, which is later used for dropdown/multiselect attributes.

Frontend Model displays the attribute at the frontend side.

How would you add dropdown/multiselect attributes?

You can create attributes through the setup script (Vendor \ Module \ Setup \ InstallData or Vendor \ Module \ Setup \ UpgradeData) or via the admin panel (for products only). In order to create dropdown / multiselect attributes, it is necessary to specify the frontend_input attribute as “select” or “multiselect” for a single or multiple selection respectively. Additionally, you must specify the source model, which will point to a list of possible values. If the source model is Magento \ Eav \ Model \ Entity \ Attribute \ Source \ Table, then you can specify the possible values of this attribute in the option property when creating an attribute through the setup script.

Example:

<?php

namespace Vendor\Module\Setup;

use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class InstallData implements InstallDataInterface
{
    /**
     * @var EavSetupFactory
     */
    protected $eavSetupFactory;

    public function __construct(EavSetupFactory $eavSetupFactory)
    {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

        $eavSetup->addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'my_attribute',
            [
                'type' => 'int',
                'label' => 'My Attribute',
                'input' => 'select',
                'source' => \Magento\Eav\Model\Entity\Attribute\Source\Table::class,
                'required' => false,
                'option' => ['values' => ['Value 1', 'Value 2', 'Value 3']]
            ]
        );
    }
}

Magento 2 Certified Professional Developer Guide Screenshot 43

What other possibilities do you have when adding an attribute (to a product, for example)?

EAV attribute has several features that we can specify.

Magento\Eav\Model\Entity\Setup\PropertyMapper class contains the conversion of property names in the setup script into EAV attribute property in the database.

Feature in setup scriptFeature in the databaseDefault value
attribute_modelattribute_modelnull
backendbackend_modelnull
typebackend_typevarchar
tablebackend_tablenull
frontendfrontend_modelnull
inputfrontend_inputtext
labelfrontend_labelnull
frontend_classfrontend_classnull
sourcesource_modelnull
requiredis_required1
user_definedis_user_defined0
defaultdefault_valuenull
uniqueis_unique0
notenotenull
globalis_global\Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL

You can also specify:

  • sort_order – attribute position, recorded in eav_entity_attribute
  • group – adds attributes in a certain group
  • option – the list of values for dropdown/multiselect attributes

Additionally, Magento/Catalog has the following properties (according to \Magento\Catalog\Model\ResourceModel\Setup\PropertyMapper):

Feature in setup scriptFeature in databaseDefault value
input_rendererfrontend_input_renderernull
globalis_global\Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL
visibleis_visible1
searchableis_searchable0
filterableis_filterable0
comparableis_comparable0
visible_on_frontis_visible_on_front0
wysiwyg_enabledis_wysiwyg_enabled0
is_html_allowed_on_frontis_html_allowed_on_front0
visible_in_advanced_searchis_visible_in_advanced_search0
filterable_in_searchis_filterable_in_search0
used_in_product_listingused_in_product_listing0
used_for_sort_byused_for_sort_by0
apply_toapply_tonull
positionposition0
used_for_promo_rulesis_used_for_promo_rules0
is_used_in_gridis_used_in_grid0
is_visible_in_gridis_visible_in_grid0
is_filterable_in_gridis_filterable_in_grid0

Describe how to implement the interface for attribute frontend models. What is the purpose of this interface? How can you render your attribute value on the frontend?

To create Frontend model, create a class, inherited from Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend, and override getValue method.

Then, set frontend_model as the name of the newly created class.

class TestFrontend extends \Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend
{
    public function getValue(\Magento\Framework\DataObject $object)
    {
    	$attribute_code = $this->getAttribute()->getAttributeCode();
        $value = $object->getData($attribute_code);
        return nl2br(htmlspecialchars($value));
    }
}

The purpose of the interface is to decrease the code dependency (dependency inversion principle).

Identify the purpose and describe how to implement the interface for attribute source models

The model is used for providing a list of attribute values for dropdown/multiselect attributes. Source model realization example:

class TestSource extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
{
    public function getAllOptions()
    {
        if (!$this->_options) {
            $this->_options = [
                ['label' => __('Label 1'), 'value' => 'value 1'],
                ['label' => __('Label 2'), 'value' => 'value 2'],
                ['label' => __('Label 3'), 'value' => 'value 3'],
                ['label' => __('Label 4'), 'value' => 'value 4']
            ];
        }
        return $this->_options;
    }
}

For a given dropdown/multiselect attribute, how can you specify and manipulate its list of options?

The values are stored in the eav_attribute_option_value table if the source model is the Magento \ Eav \ Model \ Entity \ Attribute \ Source \ Table class or is inherited from it. The values can be added when creating an attribute in the option property, or you can call the Magento \ Eav \ Setup \ EavSetup-> addAttributeOption ($ option) method.

If the source model is not inherited from Magento \ Eav \ Model \ Entity \ Attribute \ Source \ Table, then, to change the list of values, you can:

  • create a plugin on the source model on the getAllOptions method
  • create a new source model, inherited from the mutable class, change the behavior of the getAllOptions method and specify the new source model in the attributes

Identify the purpose and describe how to implement the interface for attribute backend models. How (and why) would you create a backend model for an attribute?

Backend modules are created with a purpose to upload / save / delete / validate attribute values.

Example of attribute value validation:

class TestBackend extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
{
    public function validate($object)
    {
    	$attribute_code = $this->getAttribute()->getAttributeCode();
        $value = $object->getData($attribute_code);

        if ($value == 'test') {
        	throw new \Magento\Framework\Exception\LocalizedException(__("Value can't be test"));
        }

        return true;
    }
}

Describe how to create and customize attributes. How would you add a new attribute to the product, category, or customer entities? What is the difference between adding a new attribute and modifying an existing one?

Setup scripts are applied to create or modify an attribute

Vendor\Module\Setup\InstallData и Vendor\Module\Setup\UpgradeData.

Product attributes can also be created via the admin panel.

To add an attribute, use Magento\Eav\Setup\EavSetup->addAttribute($entityTypeId, $code, $attr) method, for modification – Magento\Eav\Setup\EavSetup->updateAttribute($entityTypeId, $id, $field, $value = null, $sortOrder = null). However, if addAttribute is called and the attribute already exists, then updateAttribute method will be called automatically.

Therefore, if you apply addAttribute method, there is no difference between adding a new attribute and modifying the existing one.

Vlad Yunusov banner
Vlad-Yunusov

Tell us about your project

Get in touch with our team. Send us an email at [email protected] or call us 1 650 353 2301

Send request