The following is a collection of my experience with the EAV system in Magento. It contains all the facts I needed early on in my Magento developer career. Being a reflection of a personal experience it may be incomplete, obscure, or overladen with details. Please comment if you have a suggestion on how to improve it. If you need a clarification on some part of the text below, please ask. If there is an error – point it out. Thank you!
The EAV system is one of the most complex part of Magento shop software. It is also the most controversial and often cited as a root of performance problems in shops that have to handle large and complex product databases. When developing Magento extensions these problems can be exacerbated by failure to properly use the EAV implemented in Magento, which often happens due to a great effort that is required to understand it. For me, as probably for many other Magento developers, it has been a lot of lessons learned hard.
Before diving into details of the Magento’s EAV, it is necessary to learn a bit about the origins of EAV and its general principles. EAV has quite a long history. Some of its earliest applications were storage systems for clinical data back in 1970s. As a storage method EAV borrows from early object-oriented languages. SIMULA 67 is cited as one such influence. Functional languages such as LISP are also known to have contributed to the development of EAV. They contain storage structures that record object information in attribute-value pairs – a principle fundamental to EAV.
The most widely used way to store entities is implementing attributes as columns and entities as rows. This is sufficient for most tasks and has been efficiently implemented in relational databases. However, if you work with entities that have a large or variable, or large and variable, number of attributes, columnar representation becomes difficult. MySQL, for instance, has a hard limit of 4096 columns per table. Oracle has even less: 1000. Microsoft SQL Server offers up to 30,000 columns. But what if you must deal with entities that have many hundred thousands of possible attributes? And what if each entity has only a few attributes with values? What if the data is sparse?
The problem of sparseness can be addressed by row modelling. Consider an e-commerce application that generates and stores invoices. Potentially invoices can have every single product in the database as a position. But in reality they contain only a small percentage of products sold in the shop, i.e. only few possible positions (attributes) have values. Having a column for every product in the inventory would make a very sparsely populated table. Nobody does that. Instead, invoice positions would be stored elsewhere as a list referencing product entities. This approach solves the problem of volatility, which in our example would be the changing number of products in the shop inventory, i.e. varying number of attributes. The problem of sparseness is also being addressed here – only attributes (invoice positions) with values are stored. Actually, using row modelling for an invoice positions table is a limited example of an EAV design.
EAV Design Basics
EAV generalizes row modelling by saving all entity attributes affected by sparseness or volatility in one or several tables, which store data in attribute-value pairs. EAV becomes especially useful when the following conditions are present:
- Entity attributes vary significantly in terms of data type. In our example invoice positions are of the same type and can be stored in one table, which makes row modelling sufficient to solve the problem. But if you have a set of attributes requiring integer, boolean, datetime, or any other data type, one table would not be enough. Medical data management systems, for example, often face this problem when storing data from clinical questionnaires, whose individual entries (attributes) are represented in different data types (for this and many other reasons EAV’s most popular application is medical software).
- The number of possible entity types is huge, and entity types have individual sets of attributes; even if the number of attributes in every set is relatively small. Staying with our e-commerce example, imagine a shop that sells a very diverse range of products. Each product is described by an individual set of attributes, which is not applicable to other products. Attempting to store such products in a single table would again require a column for every possible attribute, while every row would use only a few of them. Such table would consist mostly of null values.
- Some attributes are common to all (or at least some) entity types, while other are individual and sparse. In this case a hybrid EAV approach is used. Common attributes are stored in one table, one row per entity. Entity type-specific attributes are stored in attribute-value tables to rectify their sparseness. The decision to use EAV in such cases is based on the number of hybrid classes in the system. With only few of them it may be more practical to consider using one or more specially designed row-modelled tables instead of implementing an EAV design.
E for Entity
An EAV system uses at least one “entity” table to store basic entity information. The minimum information required is a unique key, which is referenced by tables storing entity attributes. In a pure EAV design only one “entity” table is necessary to store entity IDs and optionally the entity’s creation timestamp. An extension of this principle is an inclusion of a column containing entity type. This way entities, which do not use EAV (store their data in columns and rows of a single table), could still be referenced by a global “entity” table. The application then could use the entity type information to choose the way to save or load entities. Since this approach allows both EAV and non-EAV entities it is referred to as a mixed-schema design. An EAV system can also have multiple “entity” tables: one for each entity type. This is how it is done in Magento. The tables catalog_product_entity, catalog_category_entity, or customer_entity are such class-specific “entity” tables.
A for Attribute
It is hard to imagine a practical EAV system without an infrastructure to store and manage attribute metadata. Attribute metadata require minimum one table to store properties that describe attribute data types, roles, applicability, and other relevant attribute aspects. In Magento this table is called eav_attributes. The columns of this table represent properties shared by all EAV attributes in the system. Magento diverts a bit from the pure EAV by introducing attribute metadata tables that are class-specific. We can find two such tables, catalog_eav_attributes and customer_eav_attributes. The former table is responsible for attribute metadata, which is used by attributes of the catalog entity types (catalog_product` and ``catalog_category). The latter contains metadata available only to the attributes of the customer entity type. So, what kind of metadata is generally used by EAV attributes?
- Validation metadata, which represents a wide range of attribute properties: data type, default value, value uniqueness, validation rules, acceptable range of values, or value source dictionary. The data type information can refer to tables, which store this data type’s values.
- Presentational metadata, which defines how the attribute data is presented to users. This information ranges from simply storing a user-friendly caption to providing references to specific presentation structures required to render complex data types.
- Grouping metadata, which describes rules used to organize attributes. Attribute grouping can be presentational or functional. Presentational grouping defines the way attribute data is categorized before being displayed to users. This grouping serves to simplify attribute data management, which otherwise would be complicated given the usually high number of attributes in EAV systems. Magento defines attribute groups for this purpose. You can see attribute groups in action in your shop’s backend in product edit forms. The tabbed design of these forms is defined and controlled by attribute groups. A functional grouping organizes attributes into sets that can be assigned to entity types, which have different functionality. Magento offers attribute sets as such an instrument. Attribute sets comprised of different attributes can be assigned to entity types, or even individual entities, to reflect their varying functional requirements.
- Descriptive metadata, which is used to store commentary about the attribute’s role in the data domain. In Magento this type of metadata is optional and is represented by a column called note in the eav_attributes table.
Attribute metadata is also used as a reference to classes in the system’s code base that are responsible for processing attribute information. Magento’s EAV attributes have a backend_model property, which points to a PHP class that defines how the attribute data is loaded, validated and saved.
V for Value
The earliest EAV designs (such as the first versions of the HELP system) used to represent every value of every attribute as the same data type: string. Over the years this method has been proven ineffective. It presents numerous challenges in indexing, range searches, and comparison operations; especially if the data is numeric in nature. Several approaches exist to store attribute values of varying data types:
- Use only one table and add a column for every possible data type. An additional column indicates which data type column contains a value for any given row. Other columns in the row would have null values. Some RDMBS index null values and this will add a certain overhead especially when the value table will grow large.
- Use a table per data type. Such tables will have at least three columns: attribute id, value, and a reference to the entity object, whom this value belongs to. Because of the small number of columns such tables are often called “skinny”. Magento goes even further by offering separate skinny tables for every data type of every entity type. For example: catalog_product_entity_int, catalog_category_entity_int, customer_entity_int, and customer_address_entity_int – four tables for integer attribute values of four different entity types.
- Use one table and a variant type column for every attribute data type. This last approach I add only for the sake of completeness. The variant data type is unique to Microsoft SQL Server and was designed for convenient programming in loosely typed languages. Using this type brings certain risks (operand type clash) as well as performance considerations.
Complex data types, which are not supported by the RDBMS, can still used in an EAV system. They can be represented as entities (think of product object in an invoice item) and referenced by their id in the main entities table. In a mixed-schema EAV design these entities can be either EAV or regular row-column type.
Module Mage_Eav
In the core of Magento EAV lies the Mage_EAV module. It is a layer between the EAV data structures and the shop domain models, such as product, category etc. This module contains classes to access and manipulate data of every EAV entity in Magento. It also provides tools to manage attribute metadata. The organization of the module is typical for Magento. Its “Model” directory contains models and resource models responsible for loading, updating, and saving entities and attribute data. Its etc/config.xml contains important settings such as list of tables used by the module’s classes and definitions for a cache system to keep attribute data readily available. The block classes extend the admin backend with grids and forms to manage product attributes. The latter are the only attributes that can be created or modified that way. To manage attributes of other entity types you must use install scripts, or extend the Mage_Eav models, or write you own classes.
The Mage_Eav_Model_Entity_Setup class will provides basic functions required to install and update EAV entity types and attributes via Magento install scripts. Its notable extensions are Mage_Catalog_Model_Resource_Setup and Mage_Customer_Model_Resource_Setup, which are used for installing and configuring EAV metadata for the Mage_Catalog and Mage_Customer modules, respectively. If you need to install your own entity type or add an attribute to an existing one, use one of these classes as a setup resource, or write your own child class.
Another prominent member of this module is Mage_Eav_Model_Config. It plays an important role in Magento’s EAV, and because of it we shall start the detailed discussion of the module with this class.
Mage_Eav_Model_Config
The EAV metadata in Magento is quite complex and is distributed across many tables. Magento uses singleton objects of this class to efficiently access the metadata and provide it to other objects when needed. The class Mage_Eav_Model_Config works together with its resource model Mage_Eav_Model_Resource_Config to access the database and load the metadata into protected properties of a config singleton object. The metadata come in form of object collections: attribute models, attribute sets, product types, etc. Collecting metadata works by the principle of “lazy loading” – objects are not fetched from the database until they are requested. Once loaded the objects remain in the config singleton and are returned to the following data requests without querying the database. The loaded data is preserved within the current HTTP request. After the HTTP request is processed it is discarded. The new request will initialize a new config singleton object and load the data again.
Mage_Catalog_Model_Config extends this class and adds more functionality required by the catalog entity types’ metadata.
The following information is stored in the config singleton:
- Entity type by code. Requesting entity type “catalog_category” will return a Mage_Eav_Model_Entity_Type object with information about attribute model class, additional attribute table (catalog/eav_attribute) and so on.
- Codes of all attributes of the entity type, in an array.
- Attribute object or an entire preloaded attribute collection.
For catalog entity types even more metadata is provided:
- Attribute groups, which are accessible by id or name. Catalog attributes are organized into groups, and these data contain their IDs and names, e.g. “64” or “description”.
- Attribute set id or name. Product attributes can be assigned to a set, which then is applied to products that share the same attributes. Sets could be, for example, “furniture”, “CPUs”, or “jewelry”.
- List of attributes that product lists can be sorted by (sortable attributes).
- List of attributes that can be used in product listings (the attribute with this property will get into the flat table and can be accessed from the product listing collections)
- Product type names or product types. Product types (for example, simple, configurable, or downloadable) can have different attributes even if they share the same attribute set with other types. Each product attribute can be set to apply for certain product types. Product types are defined in the config node global/catalog/product/type.
- Attribute sets and attribute groups as object collections.
Some examples of config objects used by Magento models:
Whenever you need to access information on some attribute property, or any other EAV metadata, use these config objects.
Mage EAV Entity Resource Models
The table eav_entity_type lists 28 entity types in Magento (v. 1.7.0). But only four of them are implemented as EAV. For these entity types Magento offers resource models that connect them to their data. This simplified diagram shows the inheritance hierarchy of Magento entity resource classes.
In the center of this hierarchy stands the class Mage_Eav_Model_Entity_Abstract. It implements interface Mage_Eav_Model_Entity_Interface, which currently is empty. But what’s more important is that this class extends Mage_Code_Model_Resource_Abstact. This makes it a resource model, even if a diversion from the common class naming convention is a bit confusing. As a resource model Mage_Eav_Model_Entity_Abstract contains all the functionality necessary to access data sources, i.e. the database.As an abstract class Mage_Eav_Model_Entity_Abstract can’t be instantiated, and the real work is performed by its extensions. Of the four EAV entity types catalog_category and catalog_product use resource models that do not extend Mage_Eav_Model_Entity_Abstract directly. Another abstract class Mage_Catalog_Model_Resource_Abstract comprises functionality that is shared by both catalog entity types. Type-specific resource model extensions are Mage_Catalog_Model_Resource_Category and Mage_Catalog_Model_Resource_Product. Other two EAV entity types, customer and customer_address have their own resource model classes: Mage_Customer_Model_Resource_Customer and Mage_Customer_Model_Resource_Address.
Mage_Eav_Model_Entity_Abstract also has extensions in the Mage_Sales module. I, however, did not encounter these classes in action. Instead, the sales entities have resource models that connect them to flat tables. It has probably been done to improve performance. EAV sales entities such as order or quote would be loaded and manipulated during the checkout, where performance is demanding, especially in heavy-load shops. EAV would have added too much overhead in this critical process. Cashing EAV data, like in the catalog, is problematic in the checkout; so using flat tables in the Mage_Sales module is simply more practical. The EAV functionality, which is left in this module, exists presumably for backward compatibility.
As resource models the extensions of the Mage_Eav_Model_Entity_Abstract class are tasked with loading, updating, and saving EAV entities. When doing that EAV resource models bind the EAV entity model functionality with the functionality of its attributes’ models. For every operation on data (after_load, validate, before_save, after_save, before_delete, after_delete) an EAV resource model performs “attribute walking” (yep, the function is called walkAttributes()). It loads all the object’s attributes and calls a corresponding function of their data models. So, for example, when deleting a customer, not only the customer entity will be deleted from the customer_entity table, but also every customer attribute will be called up in a loop, and its data model will delete attribute data for the given customer id.
There is one more resource model extending Mage_Eav_Model_Entity_Abstract. The class Mage_Eav_Model_Entity is a default resource model and is used in cases when entity type is not yet defined, and only to set the entity type. Then a type-specific resource model takes control.
Magento EAV Attributes
Magento implements its EAV attributes as models, whose classes comprise the following inheritance hierarchy.
Like any other Magento model EAV attributes have Mage_Core_Model_Abstract as the starting point of the class hierarchy. The EAV-specific functionality is first defined in the abstract class Mage_Eav_Model_Entity_Attribute_Abstract. It extends the interface Mage_Eav_Model_Entity_Attribute_Interface, which theoretically would be setting functional requiremets for the EAV attribute models, but is empty. Further functionality refinement comes in the class Mage_Eav_Model_Entity_Attribute. This class can be instantiated and sometimes is used in a singleton role to provide access to its array of all attribute IDs. Whenever the system needs to find out, which attribute_code (attribute name) refers to what attribute ID it calls Mage_Eav_Model_Entity_Attribute::getIdByCode() (the actual function is inherited and resides in the abstract class, so don’t be confused by this link). But more often this class is employed as a default attribute model. When an attribute is being used in isolation from an entity type, its model is an instance of the `Mage_Eav_Model_Entity_Attribute class.
The concrete implementations of attribute models of the main entity types are further down the hierarchy. Thus attributes of the customer entity type have the Mage_Customer_Model_Attribute model. Catalog entity types also have their own model called Mage_Catalog_Model_Resource_Eav_Attribute. The naming convention, unfortunately, isn’t always straightforward in Magento. In this case despite the word “Resource” in its name, the class is not a resource model. It is a descendant of the Mage_Core_Model_Abstract class (indirectly, the inheritance path is Mage_Eav_Model_Entity_Attribute -> Mage_Eav_Model_Entity_Attribute_Abstract -> Mage_Core_Model_Abstract). Its resource model is actually Mage_Catalog_Model_Resource_Attribute.
Another attribute model in the Mage_Catalog module is Mage_Catalog_Model_Entity_Attribute. This one is almost unused. The only time you come across it is in the user wish list grid in the shop’s administration backend. There it is used only to load the product name attribute via the loadByCode function, which it has inherited anyway. Ignore this class.
Encapsulating attribute metadata and providing the system with an access to it is the single most important role played by attribute models. In this task metadata is presented in form of attribute model properties, which are loaded from attribute metadata table. The main metadata table eav_attributes contains properties shared by every attribute in Magento’s EAv system. Entity type customer and catalog entity types catalog_category and catalog_product have additional attribute metadata tables: customer_eav_attribute and catalog_eav_attribute, respectively.
The topic of attribute properties deserves a detailed discussion. I will list them one by one and explain their meaning.
- attribute_code – This is, basically, the attribute name. If you need to resolve an attribute code into an id, use the attribute model’s loadByCode() function like in this example.
- attribute_model – This property points to a class that contains the attribute’s model. As it has been said above, some entity types have specific attribute models. Thus, attributes of the catalog entities (catalog_category and catalog_product) have Mage_Catalog_Model_Resource_Eav_Attribute as attribute model, while the customer entity type’s attributes model is Mage_Customer_Model_Attribute. The values for this property are not set in the database. Instead, when loading attribute models, the system will analyze to which entity type the given attribute belongs to, and assign either an entity-type specific model or the default one (Mage_Eav_Model_Entity_Attribute). How does the system know, which entity type has a specific attribute model? This data is stored in the table eav_entity_type in column attribute_model. The EAV config object (Mage_Eav_Model_Config) loads this information while initializing the system’s entity types.
- backend_model – Every entity attribute has a so-called “backend” model assigned to it. This model defines how the attribute data is handled when the entity object is saved or deleted. During these operations the object’s model performs “attribute walking” by calling functions afterLoad(), beforeSave(), afterSave(), beforeDelete() and afterDelete() on the attribute backend model. See Mage_Eav_Model_Entity_Abstract::walkAttributes(). The EAV Attribute property backend_model is a big topic. For its detailed description please refer to the section EAV Attribute Property backend_model.
- backend_type – Backend type indicates in which “skinny” table the attribute’s values are stored. Backend types can be varchar, int, text, decimal, or datetime; and their values are stored in entitytypename_entity_varchar, entitytypename_entity_int, entitytypename_entity_text, entitytypename_entity_decimal, or entitytypename_entity_decimal, respectively (replace entitytypename with customer, catalog_product, or catalog_category). The backend type static is a special case. Attributes of this type store their data in the entity’s main table, even though the data can be int, decimal, or varchar.
- backend_table – This property is closely connected to the attribute’s backend_type, and its values are dependent on what is set in the backend type. That is why the column backend_table in the table eav_attribute is empty. Despite the dynamic generation of backend_table values, you can explicitly set a table name and store it in the database. The database value will have precedence.
- frontend_model – Frontend models point to classes that are responsible for the attribute’s presentation to the user. For a more detailed description of these classes see EAV Attribute Property frontend_model.
- frontend_input – This property defines, what kind of input element is used for the attribute in HTML forms. See more on this property and its role here: EAV attribute Property frontend_input.
- frontend_label – This is a user-friendly name of the attribute. It is displayed next to the attribute input element in admin backend forms or in grid column titles. These values can also be displayed to shop customers. For example, the sorting options in product listing pages are comprised of the frontend_labels of the sortable attributes (the labels are actually used as translation keys; but if no key is found in the localization files – the frontend_label value will be shown to the customer as is).
- frontend_class – The function getClass() of the attribute’s frontend model uses the frontend_class value to assign CSS classes to the attribute’s input element. You can set a CSS class that your custom JavaScript validator can pick up to check the input values against whatever validation rules you want.
- source_model – Source models are mainly used by attributes with frontend_input of type select or multiselect. Source models contain functionality that allows such attributes to have a list of options to choose from. For more details refer to EAV attribute property source_model.
- is_required – When set to true property indicates that this attribute must have a value. The frontend_model will add a required CSS class to the attribute’s HTML input field to enable the client-side JavaScript validation.
- is_user_defined – This property is used to distinguish between system attributes and attributes created by shop users. The former may not be deleted – and that is why the edit form for such attributes doesn’t display the “delete” button. You still can delete system attributes programmatically, but this would be a bad idea. For attributes created by users in the backend, the backend_type property will be implicitly set using the value the user selects for the frontend_input. Also, it is possible to change the “unique” requirement (which mandates that values can not be shared by other products) for user created attributes. Changing this requirement is not allowed for the system attributes.
- default_value – You can provide a default value for the attribute. A default value will come pre-entered into the form input field, or will be used when an entity is created programmatically (e.g. product import), provided the attribute has no explicitly set value.
- is_unique – Setting this attribute to 1 will command the system to check that no two or more entities of the given type share the same value for this attribute. An example could be product SKUs or bar codes.
- note – You can enter a short descriptive text into this field, if you need a tip displayed next to the attribute’s input field in the backend. For example, see the “Meta Description” field in the product edit form.
EAV Attribute Property backend_model
The role of attribute backend model is to process attribute data according to its type whenever the parent entity object is loaded, saved, or deleted. A reference to a backend model class can be set in a database in the table eav_attributes or assigned dynamically when attribute is loaded. In the latter case the system uses the default attribute backend model Mage_Eav_Model_Entity_Attribute_Backend_Default, which extends the abstract class Mage_Eav_Model_Entity_Attribute_Backend_Abstract. Sometimes the attribute’s data type requires functions other than what the default backend model provides. In this case such functionality can be implemented in a custom class extending the abstract backend model. All backend models implement interface Mage_Eav_Model_Entity_Attribute_Backend_Interface. This means they all will have the following minimal set of public functions:
- getTable() – returns the table name (or, more precisely, configuration node pointing to the table name), which stores the attributes data. Think of “skinny” attribute-value tables, for example, customer_entity_varchar, or catalog_product_entity_decimal.
- isStatic() – tells if the attribute is static. Static is the default value for attribute field backend_type. Static attribute values are stored in the main entity table (i.e., catalog_product_entity or customer_entity) and not in the “skinny” EAV attribute-value tables.
- getType() – returns the attribute backend type. They can be varchar, static, int, text, decimal, or datetime. The type defines, in which “skinny” table the EAV entity saves the value of its attributes. The columns of a “skinny” table are: entity_id (references the entity), entity_type_id (references to the ID of the entity’s type: customer, catalog_product etc), attribute_id (pointing to the attribute whose value it is), value (in format corresponding to the attribute’s type: int, decimal, datetime etc). In a case of a multi-store environment where entities can have different values for the same attribute, the store_id column can be used.
- getEntityIdField() – returns the name of a column in EAV attribute tables, where entity_ids are stored. Default name for such column is entity_id; but custom naming is possible – and that is why this function exists.
- setValueId($valueId) – sets the ID of a row containing the entity attribute data.
- getValueId() – returns the ID of a row containing the entity attribute data.
- getEntityValueId($entity) – entity values can be stored in an attribute backend data model instance. They are packed into a protected field as an array, where keys are entity_ids, and values are the IDs of the rows in the skinny table. This function retrieves the data row ID for the given entity.
- setEntityValueId($entity, $valueId) – sets the ID of a row containing the attribute data for the given entity.
The following functions implement custom data manipulation for attribute values of the $object variable. The latter can be a customer, customer address, product, or category object
- afterLoad($object) – processes object attribute data after the object is loaded.
- beforeSave($object) – prepares attribute data before saving the object into the database.
- afterSave($object) – processes attribute data after the object is saved.
- beforeDelete($object) – performs operations on attribute data before the object is deleted.
- afterDelete($object) – processes attribute data (deletes it, in most imaginable cases) after the parent object is deleted.
A quick overview of some of the attribute backend models
There are 60 attribute backend model classes in Magento Community 1.7.0. Not all of them are actively in use. Sales entities, for instance, use flat tables, but retain EAV implementations. The following core modules contain extensions to the abstract attribute backend model:
- Mage_Eav
- Mage_Catalog
- Mage_Customer
- Mage_GiftMessage
- Mage_Sales
A simplified inheritance hierarchy of the backend model classes is as follows:
The models of the Mage_Eav module provide extensions for the common attribute backend model types, such as
- array: by extending the beforeSave() function this model ensures that entity attributes of array type will have their data saved as an imploded string. There is no attribute with such backend type in the Magento core, but should you need one – this is it.
- time_created and time_updated: their respective overrides of the beforeSave() function set the entity’s updated or created time to the current time.
- datetime: formats the date according to the internal rules before saving the attribute data into the database
- increment: fetches a new increment id from an increment model used by the given entity’s type.
- serialized: serializes the attribute data into a string before saving it into the database, and unserializes the data after loading it from the database.
- store: this attribute type is basically an integer store_id. Its backend data model ensures that the attribute’s entity always has a store_id set: before saving the store_id into the database it replaces null data with the current store_id from the request context.
The module Mage_Catalog adds more backend models used by attributes of the catalog_category and catalog_product entity types (under paths catalog/product_attribute_backend and catalog/catalog_attribute_backend).
catalog_product attribute backend models:
- boolean: this type is extended by msrp – ‘manufacturer suggester retail price’.
- customlayoutupdate: extends validation of the attribute value to ensure that it is a valid layout update (this model is also applicable to the attribute custom_layout_update of the catalog_category entity type).
- recurring: is an extension of the serialized attribute type, which adds additional functionality regarding product recurring profiles.
- sku: this type adds additional validation rules for product SKUs (checks if the value does not exceed 64 characters).
- startdate: this extension of the datetime type makes sure that products with special prices also get a proper start date for the sale action (current date time of the product saving moment).
- urlkey: if no URL key has been provided explicitly, a URL key will be generated from the product’s name in the beforeSave() function.
The price backend model types and the product price functionality in general will be discussed in detail in a chapter about catalog products:
The media backend model type attribute is quite complex and also requires a chapter of its own:
catalog_category attribute backend models:
- image: is similar to the product attribute model under the same name: it adds an image upload functionality.
- urlkey: same functionality as in the product URL key attribute model.
- sortby: attributes of this type contain sorting options for category product listings. The extended validate() function ensures that they are valid for this role.
The module Mage_Customer contains a number of its own attribute backend data models:
- billing and shipping: these attributes contain reference IDs to the customer’s default billing and shipping addresses. The afterSave() function of this model checks if the POST request contains addresses marked as either make my default billing address or make my default shipping address, and sets such addresses as values to these attributes.
- boolean: this extension of the abstract data model ensures that attributes of this type will have their empty values replaced with false before saving data into the database.
- password: attributes of type password have an additional validation rule (must match value in the confirmation field). Also, before saving the password into the database its value will be checked for the minimum length (6 characters hard coded minimum length) and hashed (default salt = 2).
- region: this backend model checks is the region (state, province) id that is about to be saved belongs to the country the customer is from.
EAV Attribute Property frontend_model
Another important property of the EAV attribute metadata is frontend_model. This property connects attributes to classes, which define how the attribute is rendered in HTML. Don’t let the word frontend confuse you – it is not about how the attribute is presented to customers in the shop’s “front end”, but about the rendering of the attribute input fields in the administration “back end”. Thus, while the backend_model classes’ work is saving and retrieving the attribute data, frontend_model s are responsible for the data presentation to the user.
Class Mage_Eav_Model_Entity_Attribute_Frontend_Abstract provides a common functionality for attribute frontend models. Some of its methods deserve more attention:
- getClass() – generates a CSS class for the attribute’s input HTML element. If an attribute is required, its input field receives a CSS class required. Other CSS classes can be taken from the attribute’s frontend_class property (stored in the eav_attribute table). Some EAV entities in Magento extend their attribute metadata with a validate_rules property. This property is used to produce additional CSS classes that can be picked up by a JavaScript validator (validate-email, validate-url etc.). Validate rules are stored as serialized associative arrays:
array( 'max_text_length' => 255, 'min_text_length' => 1 )
- getInputRendererClass() – the catalog entities (catalog_category and catalog_product) have an additional attribute property called frontend_input_renderer. It stores configuration references to Magento block classes that extend the HTML output of the attribute’s form input elements. One such example is Mage_Adminhtml_Block_Catalog_Category_Helper_Sortby_Available (look into its function getElementHtml())
- getSelectOptions() – returns you an associated array containing attribute option values and their labels. Very useful when you need to generate a drop down or a multiselect field. Naturally will work only with select or multiselect attributes.
There are 10 classes extending the abstract frontend model. I do not count the frontend model classes in the Mage_Sales module, because I have never encountered them in action. I presume, they are left for backward compatibility, since in the current Magento version (1.7.0) the sales entities use flat tables to store their attribute data. The following diagram show the inheritance relationships of the Magento’s frontend models.
The default frontend model is represented by the class Mage_Eav_Model_Entity_Attribute_Frontend_Default. This class doesn’t contain any overridden functions of properties, but simply references to the implementation in the abstract Mage_Eav_Model_Entity_Attribute_Frontend_Abstract class. Every attribute gets the default frontend model automatically, unless it has an explicit setting in the frontend_model column of the table eav_attribute. In a clean installation of Magento Community 1.7.0 only four attributes have custom defined frontend models:
- customer_entity->dob: Mage_Eav_Model_Entity_Attribute_Frontend_Datetime
- catalog_product_entity->image, catalog_product_entity->small_image, and catalog_product_entity->thumbnail: Mage_Catalog_Model_Product_Attribute_Frontend_Image
EAV attribute Property frontend_input
This property tells the system what kind of input is used to enter values for the attribute. There is often a connection between the attribute property backend_type (which defines the storage type for the attribute data) and the frontend_input. Frontend input types hidden, multiline, and weight types have no such association. Other frontend_input types are related to backend_types as follows:
- text – varchar
- select – int
- multiline
- textarea – text
- price – decimal
- media_image – varchar
- image – text
- gallery – varchar
- multiselect – varchar
- boolean – int
These relationships come into play when you create or update an attribute via the attribute management tools in the admin backend or via Magento API. In these cases you can’t explicitly set backend_type, backend_model, or source_model. The values for these three properties will be set depending on what value does the frontend_input field have.
Note that select has an int data type. Even though select option labels can be text, the values of such attributes are always integers and reference the attribute options in the table eav_attribute_option. The option_id – option_label pairs are stored in the table eav_attribute_option_value. See more here EAV attribute property source_model.
EAV attribute property source_model
The property source_model is used by attributes that accept a value from a predefined list of options. Such attributes often have either select or multiselect frontend_input property, although this is not a requirement. Source models implement interface Mage_Eav_Model_Entity_Attribute_Source_Interface. This means that every source model is able to return a list of all possible options for the given attribute, or return an option text. The latter require a bit more explanation. The values of select and multiselect attributes are actually numerical references to option IDs. Attribute options represent a list of values that an attribute can have. All possible options for every attribute in Magento are stored in the table eav_attribute_options. This table, however, contains no values that are meaningful to a human. The option IDs are numerical and reference another table – eav_attribute_option_value. There, finally, you can find text labels that you normally see in the drop-down or multiselect input elements. The diagram below demonstrates the relationships between the skinny EAV tables, where catalog_product entity stores its attribute values, and the attribute option tables. As you can see, the skinny tables are connected to the eav_attribute (Magento’s main EAV attribute definitions table) and to the table eav_attribute_options via foreign key attribute_id. The eav_attribute_option_value table references eav_attribute_option with the option_id foreign key.
Or a more practical example demonstrating option values stored in skinny tables. Display gender attribute values for product with IDs between 29 and 33:
SELECT `skinny`.`entity_id` AS 'product_id', `main`.`attribute_code`, `main`.`attribute_id`, `skinny`.`value`, `options`.`option_id`, `values`.`value` FROM `eav_attribute` AS `main` JOIN `catalog_product_entity_int` AS `skinny` ON `main`.`attribute_id` = `skinny`.`attribute_id` JOIN `eav_attribute_option` AS `options` ON `main`.`attribute_id` = `options`.`attribute_id` AND `skinny`.`value` = `options`.`option_id` JOIN `eav_attribute_option_value` AS `values` ON `values`.`option_id` = `options`.`option_id` WHERE `main`.`attribute_code` = 'gender' AND `skinny`.`entity_id` BETWEEN 29 AND 33
This short diversion from the main topic of source models still works as an example of their main function – provide attributes with a value dictionaries. At the top of the source models inheritance hierarchy rests an abstract class called Mage_Eav_Model_Entity_Attribute_Source_Abstract. Unless an attribute has an explicitly set source model, a default model is assigned to it. The default model class is Mage_Eav_Model_Entity_Attribute_Source_Config. If you want to see attributes that use models other than default, run this query in your database:
SELECT `attribute_id`, `attribute_code`, `frontend_input`, `frontend_label`, `source_model` FROM `eav_attribute` WHERE `source_model` > ''
Summary
In this chapter we have looked into the general properties and functionality of the EAV entity attributes. These properties are defined in the table eav_attributes and shared by attributes of every Magento EAV entity types. I have focused your attention on catalog_category, catalog_product and customer entity types, because they make the most use of the Magento’s EAV system. The catalog entity types also have certain specific functionality, which due to its importance and scale I will describe in the following chapters.
EAV Attributes of the catalog entity types
The catalog entity types profit the most from the EAV biggest advantage: flexibility. Product managers can create product attributes in their shop’s backend without bothering the IT with such mundane tasks. Even if one can’t manage category attributes the same way, adding, changing or deleting non-system category attributes programmatically is also quite simple. In both cases no database schema changes are required. This flexibility comes at a price of complexity. You are fine if your job doesn’t go beyond regular attribute management. But once you are tasked with something less trivial, you must have a deep understanding of the Magento’s EAV attributes, which at the first sight can be quite frightening.
As we have seen in the previous chapter, every EAV attribute has its definition in the table eav_attributes, which contains basic metadata describing the types of attribute data, and the ways the data is saved and loaded. This information is shared among attributes of all Magento entity types. Catalog entities catalog_category and catalog_product also have some specific functionality attached to their attributes. To describe these specifics Magento uses a table called catalog_eav_attributes.
Catalog model class is Mage_Catalog_Model_Resource_Eav_Attribute and its resource model is Mage_Catalog_Model_Resource_Attribute. The non-standard naming of the model class is a bit confusing. Despite its name Mage_Catalog_Model_Resource_Eav_Attribute is not a resource model and inherits from Mage_Core_Model_Abstract.
The class Mage_Catalog_Model_Resource_Eav_Attribute provides you with access to the catalog attribute properties defined in the table catalog_eav_attributes. Lets see what they are.
- frontend_input_renderer – this property is used by the attribute’s frontend model to load a block class that is responsible for custom rendering of the attribute’s input form element. The following table contains a list of catalog attributes that make use of this property.
Attribute code | Frontend input renderer block |
---|---|
gift_message_available | giftmessage/adminhtml_product_helper_form_config |
available_sort_by | adminhtml/catalog_category_helper_sortby_available |
default_sort_by | adminhtml/catalog_category_helper_sortby_default |
filter_price_range | adminhtml/catalog_category_helper_pricestep |
msrp_enabled | adminhtml/catalog_product_helper_form_msrp_enabled |
msrp_display_actual_price_type | adminhtml/catalog_product_helper_form_msrp_price |
Go ahead and look into the function getElementHtml() of these blocks to see how each of the custom elements is rendered.
- is_global – identifies the attribute value’s saving scope. The possible values are 1 (global, indicates that the attribute’s value is valid across the entire Magento installation), 2 (website, the value is valid within a website), and 0 (store_view, the value is visible in the given store view only). These numerical scope identifiers are defined as constants in the class Mage_Catalog_Model_Resource_Eav_Attribute. The default attribute scope is global. Configurable products can use only global attributes as configurable options.
- is_visible – this property plays several roles. The search result filter collection is restricted to the visible attributes (surprisingly, this restriction is absent in the layered navigation filter collection). Only visible attributes can be used by the configurable type products as configurable options. This property also restricts a user’s ability to edit “invisible” attributes in the backend product forms, since such attributes will not be shown there. Exceptions are attributes weight_type, sku_type, and price_type – these attributes are editable, but only in connection to, respectively, the attributes weight, sku, and price. Special renderer blocks are used to display their input fields.
- is_searchable – determines if the attribute’s values will be considered when building a full-text catalog index, which is used by the Magento’s catalog search function.
- is_filterable – tells us if the attribute is used in the layered navigation. This property also plays a role in determining if the attribute’s values can be indexed by the Product Attributes indexer. For that an attribute must be filterable or visible in advanced search, and its *frontend_input* property must be either *select* or *multiselect*.
- is_comparable – attributes with this property can be used by users to compare two or more products’ features.
- is_visible_on_front – the name can be a bit confusing. This property defines if the attribute is via Magento’s XmlConnect module but does not affect the visibility of the attribute in the shop front-end. (It also plays a certain role in the attribute ability to be manipulated by the shop APIs).
- is_html_allowed_on_front – attribute values are stripped of HTML tags if is_html_allowed_on_front and is_wysiwyg_enabled properties are set to false. But if they are active, then the HTML tags will be preserved. If both these properties are true the system will process any widget templates present in the attribute’s value before rendering it. Such functionality is most valuable in a category description as well as in product short_description, description, and in_depth attributes.
- is_used_for_price_rules – the name of this attribute suggests that it controls the attribute ability to be used in catalog price rules. I, however, found no traces of it being used in this role. Other attribute properties determine if the attribute is displayed as a possible rule condition in backend. These are is_used_for_promo_rules, is_visible and frontend_input. See Mage_Catalog_Model_Resource_Eav_Attribute::isAllowedForRuleCondition() for details. I found no example of this attribute being used for any purpose at all.
- is_filterable_in_search – this property indicates that the attribute can be used in the layered navigation as a filter to the catalog search results. The values of attributes with this property set to true will be indexed by the Magento product attribute indexer.
- used_in_product_listing – attributes with this property set to true will be available to products in frontend lists such as category products, search results, cross- and upsell products, and many others. The list of product attributes filtered by this property is loaded into a singleton of the Mage_Catalog_Model_Config and becomes available to blocks, which load product collections for the frontend (Example 1, Example 2). Attributes used in product listings will also be included into the product flat tables, which are created by the flat indexer to improve the shop’s performance by storing all attributes required in the frontend in one table.
- used_for_sort_by – quite straightforward: it defines attributes, which can be used as sort-by conditions in product lists. This property can be demonstrated in the Mage_Catalog_Model_Category_Attribute_Source_Sortby source model, which is responsible for providing a list of sorting options for categories. Note the config singleton being used to get a preloaded list of sortable product attributes.
- is_configurable – indicates that the attribute can be used to create “superproducts”, i.e. products with configurable options. This function checks if the attribute can be used for this purpose (note other requirements).
- apply_to – contains a comma separated list of product types to which the attribute can apply to. Some attributes make sense only for configurable products, some can be used only by simple or dowloadable and so on.
- is_visible_in_advanced_search – attributes with this property set to true will be displayed in the advanced catalog search form, and customer can use them to build an attribute specific search query.
- is_wysiwyg_enabled – can be set for attributes that have is_html_allowed_in_front enabled. This allows adding a WYSIWYG JavaScript editor to the textarea input field in the backend.
- is_used_for_promo_rules – tells the system if the attribute can be used to generate promotion rules. Also attributes with this property will be included into the product flat index.
EAV Attribute Sets and Groups
An overview of Magento’s EAV attributes would not be complete without a few words about attribute sets and groups. Attribute sets add flexibility to the attribute system by allowing attributes to be grouped together so that different entity types (or different entities of the same type) could have only those attributes that they really need.
Attribute sets are represented by the Mage_Eav_Model_Entity_Attribute_Set class and its resource model Mage_Eav_Model_Resource_Entity_Attribute_Set. The information on the shop’s attribute sets is contained in the table eav_attribute_set. For every attribute set this table stores an ID and a name, and the ID of the entity type the set belongs to. Every entity type in Magento (the standard installation of the version 1.7.0 has 28), has at least one attribute set assigned to it. Entity type catalog_product is the only one that has more than one attribute set, probably because it is also the only entity type that makes use of multiple attribute sets. If you install the test shop data (available at the Magento’s website), you can see that it brings several attribute sets for this entity type. Shops having different product types in their inventory can benefit from grouping product attributes into sets like, ‘Cameras’, ‘CPUs’, ‘Monitors’, ‘RAM’ and so on. This greatly simplifies the product management. Multiple attribute sets are not resticted to the catalog_product entity type. Theoretically, you may get a task that would require creating attribute sets for other entity types, e.g. catalog_category or customer. However, in our overview we will discuss in detail the product attributes only.
Attributes grouped together into atttribute sets can be aggregated even further by creating attribute groups. Attribute group functionality is implemented in the Mage_Eav_Model_Entity_Attribute_Group class and in the Mage_Eav_Model_Resource_Entity_Attribute_Group resource model (the product entity type groups use an extended class Mage_Catalog_Model_Product_Attribute_Group). Attribute group data is stored in the table eav_attribute_group.
The main role of attribute groups is organizing entity attributes into tabs in the entity edit form. You might have already seen and used tabbed attribute forms when editing products and categories. The block Mage_Adminhtml_Block_Catalog_Product_Edit_Tabs is responsible for creating such tabs in the product edit form. The block Mage_Adminhtml_Block_Catalog_Product_Edit_Tabs does the same for categories.
Creating attribute sets and groups
You can create attribute sets in the shop backend. The system won’t allow you to build a set from scratch; instead, you will have to select one of the existing product attribute sets. In a clean installation you will have only one option – “Default” attribute set. After giving the new attribute set a name and choosing one of the existing sets as a template, the system will present you with a GUI, which is used to add new attribute groups and assign attributes to them. Attribute groups are inhrited from the tempate set: the system clones them for the new set. If you deside to delete the cloned groups, the groups of the original set would not be affected. The cloning of groups and attribute assignments is done by the function Mage_Eav_Model_Entity_Attribute_Set::initFromSkeleton($skeletonId).
This is not the only way to create attribute sets and groups. If you want, you can create an installation script for that – but make sure your setup class extends Mage_Eav_Model_Entity_Setup! My sample installation script illustrates this approach. I am using arrays to define my sets and groups – this feature is a remnant of a script, which I used to install numerous sets and groups in one go. But if you need to create one set only you can, of course, drop the arrays and use other variables instead. So, in the script I have defined an array consisting of an attribute set name and an ID (set to -1 until we get a valid value from the database). The keys of the $attributes array are the names of the future attribute groups; and its elements are arrays of attribute codes, which will be assigned to these groups. In a loop the scrips creates the set, adds groups to it, and assignes attributes to the set and the group. Attributes must be assigned to both the group and the attribute. The former assignment simplifies and organizes the attribute display and management in the shop backend; while the latter plays an important role in product models and collections.
The relationships between attributes and attribute sets and groups are stored in the table eav_entity_attribute, which is managed by the model Mage_Eav_Model_Entity_Attribute. Entities can load this information into their array of attributes by using the functionality provided by a singleton of the Mage_Eav_Model_Entity_Attribute_Set class.
Loading a catalog model and its attributes
As it is common in Magento, you use a resource model to load data into an instance of a Mage_Catalog_Model_Category or Mage_Catalog_Model_Poroduct class. The resource model extends the abstract class Mage_Catalog_Model_Resource_Abstract and uses its load() function. This function in turn calls its parent method Mage_Eav_Model_Entity_Abstract::load(), which does the following:
- Loads a data row from the entity type’s main table (catalog_category_entity or catalog_product_entity) for the given object. If no row is found, the system assumes a new object is being created.
- Calls the function Mage_Eav_Model_Entity_Abstract::loadAllAttributes() next. It loads attribute instances (attribute models) for the default (static) attributes of the current entity type. Besides the default attributes this function also fetches EAV attributes defined for this entity type and filters them by the attribute set, which has been assigned to the given object. For this purpose a singleton of the Mage_Eav_Model_Config class provides a function Mage_Eav_Model_Config::getEntityAttributeCodes($entityType, $object = null).
-
- Calls Mage_Eav_Model_Entity_Abstract::_loadModelAttributes($object), which loads data into the object’s attribute. The loading sequence is:
-
- Get a list of “skinny” EAV tables that store the object’s attribute data
- Prepare PDO select objects, which will be used to pull attribute data
- Execute prepared select statements and assign the retrieved data to the object’s attributes (note, here I mean not the attribute models loaded before but the object’s data array of fields, like “name”, “description”, etc.)
- After the object attributes have recieved data, the Mage_Eav_Model_Entity_Abstract::_afterLoad() calls the Mage_Eav_Model_Entity_Abstract::walkAttributes() method, which loops through all the preloaded attribute models and uses their backend models to perform whatever data manipulation is required after the attribute data is loaded into an object.
- In case you are loading a product entity object, the final stage checks if the product has options and, if yes, loads them.
With that a catalog entity object is loaded and ready to be used.
Mage_Eav_Model_Form
The class Mage_Eav_Model_Form of the modul Mage_Eav deserves some attention. This abstract class has only one child, Mage_Customer_Model_Form. The Address- and AccountController of the Mage_Customer module use this class to process post data received from customer registration and address forms (account creation, updates, shopping cart checkout in frontend and backend alike). Most of the form functionality is defined in the abstract class, and, theoretically, it can be used to process forms for EAV entities other than customer.
What is so specific about this class?
Consider it in action with AccountController::createPostAction(). This procedure creates a customer account from a post request. The form model is called in the following order:
- instantiate an empty form object
- set form code “customer_account_create”
- extract data from a post request (returns an array)
- validate the data from that array, return errors, if any
- in validation successful, compact the data array
Whats is going on behind the scenes?
Constructing the form object requires that the extending class has hard coded a module name (‘customer’) and an entity type name (also ‘customer’). This way the form will know what EAV entity it is supposed to work with.
Setting form code will provide the form attribute collection with a filter form_code = 'customer_account_create', which allows to select only those attributes, that are used by this form. The relationship between customer attributes and customer forms are set in table customer_form_attribute.
Extracting data is a bit more sophisticated. It gives us an insight into the internal mechanics of Magento’s EAV system. This function performs a loop through all the form’s attributes. The list of the attributes is a collection defined in the module, which contains the extension of the abstract form class, or in our case, Mage_Customer. A resource collection customer/form_attribute_collection is responsible for providing the form with the list of attributes. This class initializes a resource model connecting to table customer_form_attribute, which is a metadata table for the customer entity EAV attributes. Now the form knows, which attributes the customer entity has.
So the function loops through the attributes omitting invisible ones. In this loop the function creates a dataModel object for each valid attribute. This is an interesting example of factory pattern in action. Every attribute has a data model (defined in the attribute’s metadata). This data model corresponds to a class, whose instance has to be be created. To create instances of attribute data models a factory static function is employed. Meet Mage_Eav_Model_Attribute_Data::factory(). This function gets the attribute object and the entity object. And:
$dataModelClass = $attribute->getDataModel(); if (!empty($dataModelClass)) { if (empty(self::$_dataModels[$dataModelClass])) { $dataModel = Mage::getModel($dataModelClass); self::$_dataModels[$dataModelClass] = $dataModel; } else { $dataModel = self::$_dataModels[$dataModelClass]; } } else { if (empty(self::$_dataModels[$attribute->getFrontendInput()])) { $dataModelClass = sprintf('eav/attribute_data_%s', $attribute->getFrontendInput()); $dataModel = Mage::getModel($dataModelClass); self::$_dataModels[$attribute->getFrontendInput()] = $dataModel; } else { $dataModel = self::$_dataModels[$attribute->getFrontendInput()]; } } $dataModel->setAttribute($attribute); $dataModel->setEntity($entity); return $dataModel;
So what is happening here? An attribute may have a dataModel property defined. In this case the static function checks if the class is already loaded into its map and returns it. If not Mage::getModel() is used to instantiate the class object, which is then saved into the factory’s map. If no dataModel is defined, the factory uses the attribute’s frontendInput property to load one of the default attribute data models, which are found under eav/attribute_data (for example, eav/attribute_data_text).
With dataModel class object loaded, the system calls Mage_Eav_Model_Attribute_Data_Abstract::extractValue(). Each Data model implements this method. The method takes an attribute value from the request (POST request variable code matched to the attribute) and applies an input filter to it. The attribute property inputFilter defined is used at this stage to instantiate a filter object from Varien_Data_Form_Filter_(inputFilter) and to apply a filter to the POST variable.
After the attribute looping is done, the function returns an array containing a filtered input from the customer form.
Validating data. Here the process is similar to the extracting. By looping through all the attributes the function loads data models and validated the input data by calling Mage_Eav_Model_Attribute_Data_Abstract::validateValue(). This abstract function is implemented in all attribute data models. Implementation may include checking the value against a set of rules defined for the given data model. Customer attributes have a property called validate_rules (can be found in table customer_eav_attributes), which contains a serialized object with the validation rules. So the text data model loads validation rules from the attributes and uses them to validate the value. Also there is a check if the attribute is required, and if a value is provided for the required attribute. If any errors discovered, they are returned in an array. Otherwise, true is returned .
Compacting data. Despite the name, the process is simply a transfer of the validated attribute values to the entity. In a fashion similar to extracting and validation, each attribute’s data model is loaded and Mage_Eav_Model_Attribute_Data_Abstract::compactValue() is called. By using setter methods and attribute codes, the entity extending the Varien_Object class gets its data set.
Thank you for this great detailed fact page or tutorial, don’t know how to properly name it.
I don’t have any comments (yet) because i just discovered this Golden piece of information, so i can print it out, to learn about this Magento EAV topic. This info i really needed as basic to continue with developing in magento as a newcomer with Magento.
Thank you, Daniel, for your compliment!
Pingback: Creating a Custom Product Type in Magento | Solving Magento
Very nice information. I dont know how I have missed this site in my magento career. Thanks for your information, and keep this..!!
Wow what a superb article!, the history behind EAV was particularly interesting. Thank you for this gem of information.
Very useful article!!!
Good article. But is it possible to get more detailed version of this topic?
Thanks
Great article! Thanks for such useful information. I deleted a record by accident in my eav_entity_store table. Don’t know if the line matters and/or will cause problems. If the entry is important, I don’t know what value to enter. At what points are records created in this table? HELP!!!
Pingback: Magento - Criar atributo customizado (source type) - Daniel Salvagni
.it is very kind of you. I have a question maybe you could help me.
I am student and I work on a project implemented in Magento and PHP zendframework.
My question : i have a form called form1, i can submit all fields into data base. i would like to add a new text-field in this form1 and then to submit this into database.
How easy would it be to add support for Entity versioning? i.e. to tag on to content instances, what version of the Entity they had been created on and to use that version for rendering the content.
Thanks for this great post, one of very rare articles which explain Magento internals.
Found just what I was looking for!
Hi Oleg,
Normally one can’t see the forest for the trees and is therefore afraid to go in. You have provided a high level (helicopter) view of EAV that illuiminates the whole forest, making a stroll through it not only possible, but enlightening.
Errata found:
Magento offers attribute sets as such an instrument.
Attribute metadata is also used as a reference to classes in the system’s code base that are responsible for processing attribute information.
The metadata come in form o
nf object collections: attribute models, attribute sets, product types, etc.The EAV functionality, which is left in this module, exists presumably for
thebackward compatibility.Thus attributes of the customer entity type have the Mage_Customer_Model_Attribute
asmodel.In this task metadata is presented in form of attribute model properties, which are loaded from attribute metadata tables.
If you need to resolve an attribute code into an id,
For attributes created by users in the backend, the backend_type property will be implicitly set using the value the user selects for the frontend_input. For attributes created by users in backend, the backend_type property will be implicitly set using the value the user selects for the frontend_input.
The following diagram show sthe inheritance relationships of the Magento’s frontend models.
Note that select
ishas an int data type.this feature is a remnant of a script, which I used to install numerous sets and
fgroups in one go.If no row is found, the system assumes a new object is being created.
The mMost of the form functionality is defined in the abstract class, and, theoretically, it can be used to process forms for EAV entities other than customer.Customer attributes have a property called validate_rules (can be found in table customer_eav_attributes), which contains a serialized object with the validation r
iules.Thank you for the corrections!
Pingback: How Magento Database Works for Product Tables - MetaKave: Web Design, Development & CMS Works
Thank you Oleg, great article!