В данной публикации я обзорно рассмотрю структуры данных Magento 2, поддерживающих функционирование такой концепции, как EAV. Разработчикам иногда нужно выбираться из дебрей кода и пытаться обозревать места своего жизнепровождения с высоты полёта орла — это позволяет наводить фокусы на вещи действительно важные или просто большие. Вот я и выбрался.  Аббревиатура EAV раскрывается как Entity-Attribute-Value (это для тех, кто не ходил по ссылке выше). Основной "плюшкой" EAV является эффективное использование пространства БД в тех случаях, когда возможное количество различных атрибутов (свойств, параметров), которые могут быть использованы для описания вещей (сущностей), является очень широким, но количество атрибутов, которое на самом деле относится к отдельному объекту, является относительно небольшим. Хорошим примером подобного случая в e-commerce служит такое понятие, как "продукт" — значимые атрибуты продуктов "телевизор" (размер экрана) отличаются от значимых атрибутов продуктов "спальный мешок" (минимальная комфортная температура). Так что же Magento 2 предлагает для хранения данных в формате EAV? В свежеразвёрнутой базе Magento 2.3 есть 21 таблица с префиксом eav_. Все их можно разделить на три группы: Проще всего с eav_form — эти таблицы относятся к отображению некоторых EAV-данных на UI и непосредственно к размещению EAV-данных в базе не относятся (я рассматриваю только структуры данных и только с точки зрения хранения информации, а не её отображения). Для эксперимента я удалил таблицы пространства eav_form из базы и это не помешало мне оформить заказ в магазине. Так что нужно ещё поискать, где используются данные из этого пространства таблиц и насколько они нужны для функционирования Magento. Из оставшихся двух группа eav_attribute относятся к букве A(ttribute), а группа eav_entity — к букве E(ntity). Где же буква V(alue)?  Значения для атрибутов сущностей нужно искать в суффиксах имён таблиц: Можно видеть, что подобные суффиксы имеются у таблиц, начинающихся с: Простое перемножение кол-ва суффиксов (5) на кол-во префиксов (5) даёт нам общее кол-во таблиц (25) в которых предполагается хранение values-данных. Начало EAV в Magento нужно искать в таблице eav_entity_type. Именно здесь задаётся, для каких типов сущностей значения атрибутов будут сохранятся в EAV-структуре. Так вот, изначально Magento 2.3 предлагает такой вариант для следующих восьми сущностей: Следующий шаг — находим, какими атрибутами могут характеризоваться эти типы сущностей. Данная информация находится в таблице eav_attribute. Реестр атрибутов имеет замыкание на реестр типов сущностей по внешнему ключу (foreign key). В реестре атрибутов изначально 135 записей, принадлежащих 4 типам сущностей: catalog_product О чём это говорит? Ну, хотя бы о том, что остальные типы сущностей: не используют EAV-структуру для хранения данных. То есть, на каком-то этапе энтузиазм присутствовал и использование EAV планировалось для восьми типов сущностей, но по факту остановились на 4. Пространство таблиц eav_entity напоминают китайские города-призраки — из 9 таблиц пространства данные содержатся только в двух: Остальные 7 таблиц — пусты: Очень похоже на попытку унификации способа хранения значений для атрибутов сущностей в одном наборе таблиц (datetime, decimal, int, text, varchar) вместо того, чтобы иметь по 5 таблиц с соответствующими суффиксами для каждого типа сущностей. На неудачную попытку? Или это будущее EAV в Magento?   По-любому, Земля же была безвидна и пуста, и тьма над бездною, и Дух Божий в настоящем эти таблицы изначально не используются. В таблице eav_entity_type задаются типы сущностей, в таблице eav_attribute задаются сами атрибуты и их привязка к соответствующим типам сущностей. А как определить, где искать значение для такого-то атрибута такой-то сущности? В этом нам поможет поле eav_attribute.backend_type. Оно показывает, где сохраняются значения атрибутов: Для остальных типов значения сохраняются в отдельных таблицах, в названиях которых префикс соответствует типу сущности (customer_, ...) а суффикс — одному из типов данных: Т.е., значения для атрибута #79 catalog_product.special_from_date типа datetime сохраняются в таблице catalog_product_entity_datetime. Значения для атрибута #77 catalog_product.price — в таблице catalog_product_entity_decimal. Что можно интересного увидеть в таблице eav_attribute в связи с типами значений? Как я уже отмечал выше, в данной таблице описаны атрибуты только для 4 типов сущностей из 8, зарегистрированных в eav_entity_type. При этом для сущностей типа customer и customer_address все атрибуты, определённые изначально, имеют тип значений static — т.е., являются обычными колонками в таблице и никак не используют преимуществ EAV-подхода. Таблицы: изначально пусты и могут быть использованы только программным путём (т.е., через админку, без сторонних расширений, нет возможности записать что-либо в эти таблицы). Категории каталога — вот первая сущность, которая более-менее использует EAV подход в Magento. Тип сущности — catalog_category, всего изначальных атрибутов — 30, из которых не-статических — 26. То есть, значения только 4 атрибутов (children_count, level, path, position) сохраняются в таблице catalog_category_entity, остальные сохраняются в наборе таблиц catalog_category_entity_ [ datetime | decimal | int | text | varchar ]. Структура таблиц из этого набора очень похожа как друг на друга, так и на аналогичные таблицы других типов сущностей (клиентов, их адресов и т.д.): Для различных типов сохраняемых значений (datetime, decimal, int, text, varchar) меняется только тип колонки value. Данная структура позволяет сохранять отдельное значение (value) отдельного атрибута (attribute_id) отдельной сущности (entity_id) для отдельной витрины (store_id).  В связи с архитектурными особенностями Magento добавляется дополнительная связь с витриной — store_id. Таким образом возможна локализация значений одного и того же атрибута одной и той же сущности для различных витрин. Категории каталога — это первые сущности в Magento, для которых можно использовать EAV-подсистему прямо "из коробки". Задавать значения для атрибутов каталогов можно через админку.  Можно не только давать различные значения для текстовых атрибутов, переводя на язык соответствующей витрины, но и локализовывать атрибуты других типов. Например, в преддверии рождественских праздников на ru-витринах магазина для атрибута catalog_category.custom_design_from можно выставить значения 7-го января следующего года, а на en-витринах — 24-го декабря этого.  В общем-то, это тот самый тип сущностей, ради которого EAV и затевалась в Magento. Тип сущности — catalog_product, всего изначальных атрибутов — 63, из которых не-статических — 56. Структура таблиц, поддерживающих EAV для продуктов, аналогична структуре таблиц для каталогов. Но есть одно значительное отличие. Для продуктов можно создавать новые атрибуты через админку — это default'овый функционал Magento, из коробки. Если для других сущностей Magento предоставляет только EAV структуры данных в расчёте на их программное заполнение, то для продуктов реализован интерфейс, позволяющий делать это на уровне пользователя (управляющего магазином) — Stores / Attributes / Product. Для продуктов задействованы ещё две таблицы, относящиеся к EAV: По-большому счёту, они скорее относятся к отображению информации, чем к её хранению. Атрибуты продукта объединяются в наборы (set) и при создании продукта ему присваивается набор атрибутов, что позволяет при заполнении карточки продукта для, например, телевизора, выбирать набор атрибутов, относящийся именно к бытовой технике (или даже для группы продуктов "телевизоры"). Объединение атрибутов в наборы происходит в Stores / Attributes / Product / Attribute Set:  IMHO, Magento является хорошим примером того, что целесообразность применения EAV достаточно узкая. При закладке на использование EAV для 8 сущностей (eav_entity_type) EAV-нотация используется только для 4 сущностей (eav_attribute), из которых только 2 сущности имеют действительно EAV-атрибуты — catalog_category и catalog_product. Причём для catalog_category EAV-атрибуты используются не по своему прямому назначению (большое количество различных атрибутов для описания сущности при малом количестве атрибутов, относящихся к отдельному экземпляру), а для "по-витринной локализации" значений атрибутов (один и тот же набор атрибутов для сущности "категория каталога" с возможностью атрибута экземпляра иметь различные значения для различных витрин магазина).  Полноценное использование EAV применяется только для catalog_product (правда и тут есть примесь "по-витринной локализации", но это уже расширение EAV-модели, а не её профанация, как в случае с категориями). Зато с продуктами Magento раскрывает EAV по полной — Magento-приложение можно смело использовать для наглядной демонстрации принципов EAV. wiredgeese.com