Understanding the Purpose of ‘eav_’ Tables in Magento

databaseeav

I've always wondered what is the meaning of the tables :

eav_entity  
eav_entity_datetime
eav_entity_decimal
eav_entity_int
eav_entity_store
eav_entity_text

They are always empty. They are created in versions before 1.6 in app/code/core/Mage/Eav/sql/eav_setup/mysql4-install-0.7.0.php and later they carried to the install script for versions 1.6+ /app/code/core/Mage/Eav/sql/eav_setup/install-1.6.0.0.php
I saw that there is a resource model linked to one of the tables Mage_Eav_Model_Resource_Entity_Store (maybe there are others) but nothing happens to/with it.

Is there any use to these tables or is this an other "feature" that was started and not implemented like the layout version or admin breadcrumbs for example.

Best Answer

My guess is that it's part legacy and a "convenience" pattern for developers to implement "generic" entities/models.

As you've stated, the related tables are usually empty. The reason being is that none of the core EAV entities use this "default" entity table structure. These are the entity tables from a 1.8 install:

mysql> select distinct(entity_table) from eav_entity_type;
+-------------------------+
| entity_table            |
+-------------------------+
| customer/entity         |
| customer/address_entity |
| sales/order             |
| sales/order_entity      |
| catalog/category        |
| catalog/product         |
| sales/quote             |
| sales/quote_address     |
| sales/quote_entity      |
| sales/quote_item        |
| sales/invoice           |
+-------------------------+
11 rows in set (0.00 sec)

Using the Customer model as an example, we can see that the resource model Mage_Customer_Model_Resource_Customer extends Mage_Eav_Model_Entity_Abstract, Source.

Note: Prior to 1.6 the resource model for the customer entity was Mage_Customer_Model_Entity_Customer which also extended Mage_Eav_Model_Entity_Abstract, Source.

If we examine the Mage_Eav_Model_Entity_Abstract class we find a getEntityTable method. This method is used to determine which table to use when building queries during common CRUD operations. Another method that is of interest is getValueTablePrefix. It determines the prefix for the tables for data "type" tables, *_datetime, *_decimal, *_varchar and so on.

Peeking into the source for those methods (here and here).

public function getEntityTable()
    {
        if (!$this->_entityTable) {
            $table = $this->getEntityType()->getEntityTable();
            if (!$table) {
                $table = Mage_Eav_Model_Entity::DEFAULT_ENTITY_TABLE;
            }
            $this->_entityTable = Mage::getSingleton('core/resource')->getTableName($table);
        }

        return $this->_entityTable;
    }

In the above method we can see that if the the entity type does not define a custom table it defaults to Mage_Eav_Model_Entity::DEFAULT_ENTITY_TABLE. The value of that constant is 'eav/entity', which in turn gets turned into the eav_entity table (assuming there's no configured table prefix in the application). The second method I mentioned falls back on this table as a prefix if none has been configured for the given entity. If you examine the values in the eav_entity_type table for the value_table_prefix column you'll notice that they're all NULL.

public function getValueTablePrefix()
    {
        if (!$this->_valueTablePrefix) {
            $prefix = (string)$this->getEntityType()->getValueTablePrefix();
            if (!empty($prefix)) {
                $this->_valueTablePrefix = $prefix;
                /**
                * entity type prefix include DB table name prefix
                */
                //Mage::getSingleton('core/resource')->getTableName($prefix);
            } else {
                $this->_valueTablePrefix = $this->getEntityTable();
            }
        }

        return $this->_valueTablePrefix;
    }

The logic in the method is rather simple, if no value prefix is defined use the entity table name as the prefix.

I presume that since these tables have been in Magento for so long it's best to leave them in for any backwards compatibility than remove them outright. The idea that I believe they were going for was an easy to use entity/model structure that other developers could just extend a few classes and have these "dynamic" attributes that could be changed via the admin (see catalog products and customer models). Unfortunately the implementation and practice of said pattern doesn't seem to scale well and leads to problems. I've never seen this structure used in the wild, probably due to the lack of documentation and example use cases or poor performance.

I'm no core developer (or archeologist) but that's what I gather from the code and data structures, hopefully it helps shed some light.

Related Topic