Magento для PHP MVC розробників – Розширений ORM – EAV (ч.6/11)

У попередній статті про основи ORM ми оглядали два види моделей в Magento. Регулярні, або “прості” Моделі, і Моделі EAV (значення атрибуту об’єкта). Ми також говорили, що то був трохи поверхневий огляд. А в цій статті ми проведемо більш поглиблений огляд цієї частини.

ВСІ Моделі Magento взаємодіють з базою даних по наслідуванню від ланцюга Mage_Core_Model_Abstract / Varien_Object. Що перетворює прості моделі чи EAV-моделі в моделі Model Resource. У той час як всі ресурси розширюють базовий клас Mage_Core_Model_Resource_Abstract, прості моделі мають ресурси, що успадковуються від Mage_Core_Model_Resource_Db_Abstract, а моделі EAV мають ресурси, що успадковуються від Mage_Eav_Model_Entity_Abstract.

Якщо ви думаєте про це, це має сенс. Як програміст-користувач системи, ви захочете мати набір методів, які ви зможете використовувати для спілкування і маніпулювання своїми Моделями. Вас не хвилює, як виглядає бек-енд сховище, ви просто хочете отримати властивості і викликати методи, які запускають бізнес-правила.

 

 

Що таке EAV

Вікіпедія визначає EAV так:

Модель EAV – Сутність-Атрибут-Значення, або ж модель значення атрибуту об’єкта і відкрита схема – це модель даних, яка використовується в тих випадках, коли кількість атрибутів (властивостей, параметрів), які можуть бути використані для опису речей («сутності» або «об’єкту») є потенційно дуже широкою, але число, яке буде насправді відноситись до даного об’єкта є відносно невеликим. У математиці ця модель відома як розріджена матриця.

Інша метафора, що допомагає мені це краще зрозуміти: «EAV привносить деякі аспекти нормалізації до схеми таблиці бази даних». У традиційній базі даних, таблиці мають фіксовану кількість стовпців:

 

+------------------+
| products     |
+------------------+
| product_id    |
| name       |
| price      |
| etc..      |
+------------------+

+------------+----------------+------------------+---------+
| product_id | name      | price      | etc... |
+------------+----------------+------------------+---------+
| 1     | Widget A    | 11.34      | etc... |
+------------+----------------+------------------+---------+
| 2     | Dongle B    | 6.34       | etc... |
+------------+----------------+------------------+---------+

 

Кожен товар має назву, у кожного товару є ціна і т.д.

У EAV моделі кожна “сутність” (товар) змодельована мати різні набори атрибутів. EAV набуває великого сенсу для рішень в електронній комерції. Магазин, який продає ноутбуки (що варіюються за швидкістю процесора, кольором, величиною оперативної пам’яті і т.д.), буде мати більш різноманітний набір потреб, ніж у магазина, який продає пряжу (нитки мають колір, але не мають швидкості процесора і т.д.). Навіть у нашому гіпотетичному магазині пряжі деякі товари будуть мати довжину (клубки пряжі), а деякі – діаметр (спиці).

Є не так багато баз даних чи з відкритим вихідним кодом, чи комерційних, які використовують EAV за замовчуванням. Такого немає в доступності серед всього різноманіття платформ веб-хостингу. Через це інженери Мадженто побудували систему EAV з об’єктів PHP, які використовують MySQL в якості сховища даних. Іншими словами, вони створили систему бази даних EAV над традиційною реляційною базою даних.

На практиці це означає, що будь-яка модель, яка використовує EAV ресурс, зберігає свої атрибути розкиданими по декільком MySQL таблицям.

 

груба схема таблиць бази даних Magento для сутності catalog_product

 

На діаграмі представлена груба схема таблиць бази даних Magento для сутності catalog_product, як ми її бачимо в записі EAV. Кожен окремий товар має рядок в catalog_product_entity. Всі доступні атрибути системи в цілому (не тільки для товарів) зберігаються в eav_attribute, а фактичні значення атрибутів зберігаються в таблицях з таким назвами як: catalog_product_entity_attribute_varchar, catalog_product_entity_attribute_decimal, catalog_product_entity_attribute_etc.

За ментальною гнучкістю, що дає нам система EAV, також є практична користь від уникнення запитів TABLE ALTER. Коли ви додаєте новий атрибут до своїх товарів, новий рядок вставляється в таблицю eav_attribute. У традиційні системі реляційної бази даних/системі звичайних таблиць, вам потрібно б було змінити реальну структуру бази даних, що може бути надто трудомістким/ризикованим рішенням для таблиць з великими наборами даних.

Недоліком є ​​те, що немає якогось одного простого SQL-запиту, який можна було б використати, щоб дістатись до всіх даних товару. Для цього потрібно робити кілька SQL запитів або ж один великий.

 

 

Реалізація EAV

Про EAV в двох словах. Решта цієї статті є швидким оглядом того, що потрібно для створення нової моделі EAV у Magento. Це буде найяскравіше з того, що ви дізнаєтеся про Magento, і це буде тим, що 95% людей, які працюють із системою, ніколи не будуть робити. Проте розуміння того, що потрібно для побудови ресурсної моделі EAV, допоможе вам зрозуміти, що відбувається з ресурсами EAV, які використовує Magento.

Оскільки інформація про EAV досить об’ємна, ми припускаємо, що ви вже добре знайомі з попередніми статтями серії та знаєте MVC Magento і особливості згрупованої назви класу. Ми допоможемо вам на цьому шляху, але будьте готовими до навчання.

 

Модуль Weblog з допомогою EAV стилю

Ми збираємося створити ще одну модель weblog, але на цей раз за допомогою ресурсу EAV. Для початку, створіть та встановіть новий модуль, який буде відповідати наступній адресі:

http://VASH-DOMEN/complexworld

 

Якщо ви не впевнені, як це робиться, перегляньте попередні статті цієї серії.

Далі, ми створимо нову модель під назвою Weblogeav. Пам’ятайте, що це ресурс, який вважається EAV. Тому ми проектуємо і налаштовуємо нашу модель по аналогічному шляху. Отже, давайте зконфігуруємо нашу модель подібно до того, як ми це робили в попередніх уроках.

 

<global>
<!-- ... -->
  <models>
  <!-- ... -->
    <complexworld>
      <class>Alanstormdotcom_Complexworld_Model</class>
      <resourceModel>complexworld_resource</resourceModel>
    </complexworld>
  <!-- ... -->
 </models>
<!-- ... -->
</global>

 

Ви помітите, що доки немає ніякої різниці при налаштуванні звичайної Моделі і флет таблиці ресурсів Моделі.

Нам, як і раніше необхідно, щоб Magento знав про цей ресурс. Подібно до основних моделей, EAV ресурси налаштовуються в тому ж вузлі <model/> з усіма іншими.

<global>
<!-- ... -->
  <models>
<!-- ... -->
   <complexworld_resource>
     <class>Alanstormdotcom_Complexworld_Model_Resource</class>
     <entities>
       <eavblogpost>
         <table>eavblog_posts</table>
       </eavblogpost>
     </entities>
   </complexworld_resource>
<!-- ... -->
  </models>
<!-- ... -->
</global>

 

Знову ж таки, це збігається з налаштуванням регулярної моделі ресурсів. Ми прописуємо php клас у вузлі <class/>, а також розділ <entities/>, який дозволить Magento знати про базову таблицю для конкретної моделі, яку ми хочемо створити. Тег <eavblogpost/> — це назва конкретної моделі, котру ми хочемо створити, а його внутрішній тег <table/> визначає базову таблицю, яку ця Модель буде використовувати (згодом про це докладніше).

 

 

Де знаходиться цей файл?

До широкого впровадження PHP 5.3 і його простору імен, одна з хитрих (і нудних) частин Magento буде залишатись для нагадування, як <classname/> відноситься із шляхом до файлів, а потім буде перевіряти, що ви створити правильно іменовану структуру каталогів і файлів класу. Після налаштування будь-яких тегів <classname/> або URI, буде корисним спробувати створити екземпляр класу в контролері без створення файлів класу. Таким чином PHP буде видавати виняток, який скаже розробнику, який файл система не може знайти, вказуючи на його правильне розташування. Давайте продовжимо спробу у контролері IndexController:

 

public function indexAction() {
  $weblog2 = Mage::getModel('complexworld/eavblogpost');
  $weblog2->load(1);
  var_dump($weblog2);
}

 

Як і передбачалося, повинно з’явитись попередження

 

Warning: include(Alanstormdotcom/Complexworld/Model/Eavblogpost.php) [function.include]: failed to open stream: No such file or directory in /lib/Varien/Autoload.php on line 93

 

яке на додачу розповідає нам про шлях, по якому потрібно визначити новий клас ресурсів, що також служитиме в якості перевірки конфігурації. Якби ми були попереджені наступним:

 

Warning: include(Mage/Complexworld/Model/Eavblogpost.php) [function.include]: failed to open stream: No such file or directory in /lib/Varien/Autoload.php on line 93

 

ми знали би, що наша модель була неправильно налаштована, оскільки Magento шукав би модель в code/core/Mage замість code/local/Alanstormdotcom.

Отже, давайте створимо наш клас моделі:

 

Файл: app/code/local/Alanstormdotcom/Complexworld/Model/Eavblogpost.php:

class  Alanstormdotcom_Complexworld_Model_Eavblogpost extends Mage_Core_Model_Abstract {
  protected function _construct() {
    $this->_init('complexworld/eavblogpost');
  }
}

 

Пам’ятайте, Модель сама по собі є незалежним ресурсом. Регулярна Модель і EAV модель успадковуються від однакового класу. Їх ресурс і відрізняє їх.

Очистіть кеш Magento, перезавантажте сторінку, і ви повинні побачити нове попередження:

 

Warning: include(Alanstormdotcom/Complexworld/Model/Resource/Eavblogpost.php)

 

Як і очікувалося, ми повинні створити клас для ресурсу нашої моделі. Давай зробимо це!

 

Файл: app/code/local/Alanstormdotcom/Complexworld/Model/Resource/Eavblogpost.php:

class Alanstormdotcom_Complexworld_Model_Resource_Eavblogpost extends Mage_Eav_Model_Entity_Abstract {
  protected function _construct() {
    $resource = Mage::getSingleton('core/resource');
    $this->setType('complexworld_eavblogpost');
    $this->setConnection(
      $resource->getConnection('complexworld_read'),
      $resource->getConnection('complexworld_write')
    );
  }
}

 

Так, уже ми бачимо декілька відмінностей між простою моделлю та моделлю EAV ресурсів. По-перше, ми розширюємось на базі Mage_Eav_Model_Entity_Abstract класу. У той час, як Mage_Eav_Model_Entity_Abstract, як і звичайний ресурс моделі, використовує концепцію _construct, тут немає _init методу. Замість цього ми повинні задати ініціалізацію самі. Це означає, що потрібно сказати ресурсу, який ресурс для з’єднання він повинен використовувати, і передати унікальний ідентифікатор в метод нашого об’єкта setType.

Ще одна відмінність в Mage_Eav_Model_Entity_Abstract полягає в тому, що _construct – це не абстрактний метод, в першу чергу з причин зворотної сумісності зі старими версіями системи.

Отже, давайте очистимо кеш та перезавантажимо сторінку. Ви повинні побачити новий виняток:

 

Invalid entity_type specified: complexworld_eavblogpost

 

Magento скаржиться, що не може знайти entity_type з іменем complexworld_eavblogpost. Це значення, яке ми встановили вище:

 

$this->setType('complexworld_eavblogpost');

 

Кожна сутність має свій тип. Типи дозволять системі EAV знати, які атрибути використовує Модель, і дозволяє системі посилатись на таблиці, які зберігають значення атрибутів. Нам потрібно, щоб Magento знав, що ми додаємо новий тип сутності. Подивіться в MySQL таблицю з назвою eav_entity_type.

 

select * from eav_entity_type;

*************************** 1. row ***************************
entity_type_id: 1
entity_type_code: customer
entity_model: customer/customer
attribute_model:
entity_table: customer/entity
value_table_prefix:
entity_id_field:
is_data_sharing: 1
data_sharing_key: default
default_attribute_set_id: 1
increment_model: eav/entity_increment_numeric
increment_per_store: 0
increment_pad_length: 8
increment_pad_char: 0
*************************** 2. row ***************************
entity_type_id: 2
entity_type_code: customer_address
entity_model: customer/customer_address
attribute_model:
entity_table: customer/address_entity
value_table_prefix:
entity_id_field:
is_data_sharing: 1
data_sharing_key: default
default_attribute_set_id: 2
increment_model:
increment_per_store: 0
increment_pad_length: 8
increment_pad_char: 0

 

Ця таблиця містить список всіх типів entity_type в системі. Унікальний ідентифікатор complexworld_eavblogpost відповідає колонці entity_type_code.

 

 

Система і Додатки

Це ілюстрація однієї з найважливіших концепції Magento, яка багатьом людям дається дуже важко.

Подивіться на свій комп’ютер. Операційна система (Mac OS, Windows, Linux і т.д.) є програмним забезпеченням. Ваш браузер (Chrome, Firefox, Safari, IE, Opera) є додатком. Magento – це базова система (перший рівень), а її модулі – це додатки (другий рівень). Ви будуєте додатки для інтернет-магазину використовуючи систему Magento. Збиває з пантелику те, що існує багато місць в Magento, де системний код модифікується під код додатків. Конфігурація системи EAV є прикладом цього, адже вона живе в тій же базі даних, що і дані вашого магазину.

Якщо ви збираєтеся глибше розібратися в Magento, то необхідно ставитися до нього як до старої машини Type650. Тобто, це така річ, додатки до якої ви не можете ефективно програмувати до тих пір, доки у вас немає глибокого розуміння самої системи.

 

 

Створення Ресурсу Інсталятора

Отже, теоретично можливо вручну вставляти рядки, які вам потрібні в базі даних Magento для отримання робочої Моделі, але це не рекомендується. На щастя, Magento надає спеціалізовані ресурси інсталяції, які забезпечують ряд хелпер методів, що будуть автоматично створювати необхідні записи для підйому та роботи системи.

Отже, для початку, налаштуємо Інсталяційний Ресурс по схожості з будь-якими іншими.

 

<global>
<!-- ... -->
  <resources>
    <complexworld_setup>
      <setup>
       <module>Alanstormdotcom_Complexworld</module>
       <class>Alanstormdotcom_Complexworld_Model_Resource_Setup</class>
     </setup>
    </complexworld_setup>
  </resources>
<!-- ... -->
</global>

 

Далі, створіть цей файл класу:

 

Файл: app/code/local/Alanstormdotcom/Complexworld/Model/Resource/Setup.php:

class Alanstormdotcom_Complexworld_Model_Resource_Setup extends Mage_Eav_Model_Entity_Setup {
}

 

Зверніть увагу, що ми розширюємось від Mage_Eav_Model_Entity_Setup, а не Mage_Core_Model_Resource_Setup.

Потім ми налаштуємо наш скрипт інсталяції. Якщо ви не знайомі з конвенцією іменування, ви можете оглянути попередню статтю по Налаштуванню Ресурсів.

 

Файл: app/code/local/Alanstormdotcom/Complexworld/sql/complexworld_setup/install-0.1.0.php:

<?php
$installer = $this;
throw new Exception("This is an exception to stop the installer from completing");

 

Очистіть кеш Magento, перезавантажте сторінку, і поява вищевказаного винятку означатиме, що ви правильно налаштували ресурс інсталятора.

ПРИМІТКА: Ми будуватимемо наш інсталяційний скрипт крок за кроком. Якщо ви читали попередню статтю, ви знатимете, що потрібно видалити рядок setup модуля з таблиці core_resource, і очистити кеш, щоб повторно можна було запустити скрипт. В подальшому не забувайте, що при додаванні чи видаленні позицій зі скрипта, вам потрібно буде видаляти цей рядок з бази даних та очищати кеш. В звичайному ж режимі ви будете створювати цей файл і запускати його лише один раз, а всі ці дії в уроці потрібні лише для режиму розробки та навчання.

 

 

Додавання Типу Сутності

Для початку, додайте наступні рядки в скрипт встановлення Інсталятора Ресурсів, а потім запустіть його, завантаживши будь-яку сторінку (видаливши попереднє виключення):

 

$installer = $this;
$installer->startSetup();
$installer->addEntityType('complexworld_eavblogpost', array(
  //entity_model це URI, яке передається у виклик Mage::getModel()
  'entity_model'  => 'complexworld/eavblogpost',

  //таблиця відноситься до URI ресурсу complexworld/eavblogpost
  //...eavblog_posts
  'table'      => 'complexworld/eavblogpost',
));
$installer->endSetup();

 

 

Ми викликаємо метод addEntityType у об’єкті інсталятора. Цей метод дозволяє передати тип сутності (complexworld_eavblogpost) разом зі списком параметрів, що встановлюють значення за замовчуванням. Якщо ви запустите цей скрипт, то побачите нові рядки в таблицях eav_attribute_groupeav_attribute_set і eav_entity_type.

Тепер перезавантажуємо сторінку complexworld, що поверне нову помилку:

 

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'magento.eavblog_posts' doesn't exist

 

 

Створення таблиць даних

Отже, ми сказали Magento про новий тип сутності. Далі, нам необхідно додати таблиці MySQL, які будуть використовуватися для зберігання всіх значень сутностей, а також налаштувати систему таким чином, щоб вона знала про ці таблиці.

Наш Ресурс Інсталяції має метод, що називається createEntityTables, який буде автоматично налаштовувати потрібні таблиці, а також додавати потрібні рядки в конфігурацію системи. Давайте додамо наступний рядок в наш інсталяційний ресурс:

 

$installer->createEntityTables(
  $this->getTable('complexworld/eavblogpost')
);

 

Метод createEntityTables приймає два параметри. Перший – назва базової таблиці, а другий – список опцій. Ми використовуємо метод інсталяційного ресурсу getTable, щоб витягти ім’я таблиці з файлу конфігурації. Якщо ви уважно стежили за уроком, то знаєте, що за це відповідає рядок eavblog_posts. Ми опустимо другий параметр, що є масивом опцій, який ви повинні використовувати лише при розширених ситуаціях, які виходять за рамки даного уроку.

Після запуску цього скрипта ви повинні отримати такі нові таблиці в своїй базі даних:

eavblog_posts
eavblog_posts_char
eavblog_posts_datetime
eavblog_posts_decimal
eavblog_posts_int
eavblog_posts_text
eavblog_posts_varchar

 

 

Ви також отримаєте додатковий рядок в таблиці eav_attribute_set

select * from eav_attribute_set order by attribute_set_id DESC LIMIT 1
*************************** 1. row ***************************
attribute_set_id: 65
entity_type_id: 37
attribute_set_name: Default
sort_order: 6

 

Отже, давайте повернемося до нашої сторінки і перезавантажимо її:

http://VASH-DOMEN/complexworld

 

Успіх! Ви не повинні бачити ніяких помилок чи попереджень і отримати Alanstormdotcom_Complexworld_Model_Eavblogpost – без даних.

 

 

Додавання атрибутів

Останнім кроком ми повинні сказати нашому ресурсу інсталяції, які атрибути ми хочемо мати в нашій EAV моделі. Це було б еквівалентно додаванню нових колонок в звичайній таблиці інсталяції бази даних. Знову ж таки, ресурс інсталяції допоможе нам. Метод, що потрібен нам – це addAttribute.

Код з попереднього розділу просто розповідає Magento про тип сутності, який ми додали до системи. Наступні шматки коду будуть тими, які насправді додадуть можливі атрибути до нового типу в системі.

Ми зробимо це за допомогою методу addAttribute. Коли ми викликаємо addAttribute, Мадженто потрібно буде зробити кілька речей для встановлення ваших сутностей.

Для початку ми присвоїмо нашому Eavblogpost один атрибут під назвою title.

 

/* ... */$this->addAttribute('complexworld_eavblogpost', 'title', array(
  'type'       => 'varchar',
  'label'       => 'Title',
  'input'       => 'text',
  'class'       => '',
  'backend'      => '',
  'frontend'     => '',
  'source'      => '',
  'required'     => true,
  'user_defined'   => true,
  'default'      => '',
  'unique'      => false,
));
/* ... */

 

 

Гаразд, це невеликий шматок коду. Давайте розберемо його.

Першим аргументом addAttribute є код типу сутності. Він повинен співпадати з кодом, вказаним під час виклику addEntityType. Він каже Magento, яку сутність ми додаємо атрибуту, в нашому прикладі це complexworld_eavblogpost сутність. Щоб побачити інші доступні сутності, що постачаються разом із Magento, перегляньте в таблиці eav_entity_type стовпець entity_type_code.

Другий аргумент addAttribute – це код атрибута. Він має бути унікальним у межах даної сутності.

Третій аргумент насправді дуже цікавий. Це масив ключових пар значень, який описує властивості атрибута. Для простоти ми визначили один атрибут, але ви можете визначити стільки, скільки захочете, прописуючи додаткові виклики addAttribute до скрипта інсталяції.

 

 

Масив із пар основних значень, що визначає атрибут

Нарешті, ми маємо довгий список властивостей атрибуту:

 

'type'              => 'varchar',
'label'             => 'Title',
'input'             => 'text',
'class'             => '',
'backend'           => '',
'frontend'          => '',
'source'            => '',
'required'          => true,
'user_defined'      => true,
'default'           => '',
'unique'            => false,

 

Більшість з них визначають, як Magento буде створювати елемент форми у бекенді для цього атрибута, але, ймовірно, вам не доведеться мати справу з цим. Тим не менш, є одна важлива властивість, яку потрібно відмітити:

'type' => 'varchar'

 

Це визначає тип значення, яке буде містити атрибут. Раніше ми додавали таблицю для кожного типу атрибута:

eavblog_posts_datetime
eavblog_posts_decimal
eavblog_posts_int
eavblog_posts_text
eavblog_posts_varchar

 

Хоча вони не стосуються типів стовпчиків MySQL (а типів EAV атрибутів), їхні імена (varchar, datetime і т.д.) вказують на значення, які вони будуть зберігати.

 

Всі ці властивості атрибутів є необов’язковими, якщо б ми не вказали їх, Magento використовував би значення за замовчуванням. Ці значення за замовчуванням визначаються методом _prepareValues класу Mage_Eav_Model_Entity_Setup (успадкований нашим класом інсталяції).

 

// Mage_Eav_Model_Entity_Setup

protected function _prepareValues($attr) {
$data = array(
'backend_model'   => $this->_getValue($attr, 'backend'),
'backend_type'    => $this->_getValue($attr, 'type', 'varchar'),
'backend_table'   => $this->_getValue($attr, 'table'),
'frontend_model'  => $this->_getValue($attr, 'frontend'),
'frontend_input'  => $this->_getValue($attr, 'input', 'text'),
'frontend_label'  => $this->_getValue($attr, 'label'),
'frontend_class'  => $this->_getValue($attr, 'frontend_class'),
'source_model'    => $this->_getValue($attr, 'source'),
'is_required'     => $this->_getValue($attr, 'required', 1),
'is_user_defined' => $this->_getValue($attr, 'user_defined', 0),
'default_value'   => $this->_getValue($attr, 'default'),
'is_unique'       => $this->_getValue($attr, 'unique', 0),
'note'            => $this->_getValue($attr, 'note'),
'is_global'       => $this->_getValue($attr, 'global',
  Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL
),
);

return $data;
}

 

Другий аргумент методу викликає _getValue – це ключ масиву з нашого аргументу addAttribute, а третій – значення за замовчуванням. Отже, за замовчуванням Magento вважатиме, що ви додаєте атрибут varchar для текстового вводу.

 

 

Додавання інших атрибутів

Давайте додамо атрибути для контенту публікації блогу та для дати публікації. Код нижче вже виглядає як повний скрипт інсталяції:

 

$installer = $this;
$installer->startSetup();

$installer->addEntityType('complexworld_eavblogpost', array(
  'entity_model'    => 'complexworld/eavblogpost',
  'table'           => 'complexworld/eavblogpost',
));

$installer->createEntityTables(
  $this->getTable('complexworld/eavblogpost')
);

$this->addAttribute('complexworld_eavblogpost', 'title', array(
'type'              => 'varchar',
'label'             => 'Title',
'input'             => 'text',
'class'             => '',
'backend'           => '',
'frontend'          => '',
'source'            => '',
'required'          => true,
'user_defined'      => true,
'default'           => '',
'unique'            => false,
));

$this->addAttribute('complexworld_eavblogpost', 'content', array(
'type'              => 'text',
'label'             => 'Content',
'input'             => 'textarea',
));

$this->addAttribute('complexworld_eavblogpost', 'date', array(
'type'              => 'datetime',
'label'             => 'Post Date',
'input'             => 'datetime',
'required'          => false,
));

$installer->endSetup();

 

 

Отже, тепер ми маємо все для запуску нашого скрипта інсталяції. Після виклику addAttribute ми повинні мати:

  • Новий рядок у eav_entity_type для типу сутності complexworld_eavblogpost
  • Новий рядок в eav_attribute для атрибута title
  • Новий рядок у eav_attribute для атрибута content
  • Новий рядок у eav_attribute для атрибута date
  • Новий рядок у eav_entity_attribute

 

 

Поєднаємо все разом

Це, безумовно, найбільш крива модель блогу, але давайте спробуємо додати кілька рядків та повторимо їх через колекцію. Додайте наступні дві дії до свого індексного контролера:

 

public function populateEntriesAction() {
  for ($i=0;$i<10;$i++) {
    $weblog2 = Mage::getModel('complexworld/eavblogpost');
    $weblog2->setTitle('This is a test '.$i);
    $weblog2->setContent('This is test content '.$i);
    $weblog2->setDate(now());
    $weblog2->save();
  }

echo 'Done';
}

public function showCollectionAction() {
  $weblog2 = Mage::getModel('complexworld/eavblogpost');
  $entries = $weblog2->getCollection()
    ->addAttributeToSelect('title')
    ->addAttributeToSelect('content');
  $entries->load();
  foreach($entries as $entry) {
     // var_dump($entry->getData());
     echo '<h2>' . $entry->getTitle() . '</h2>';
     echo '<p>Date: ' . $entry->getDate() . '</p>';
     echo '<p>' . $entry->getContent() . '</p>';
  }

echo '</br>Done</br>';
}

 

Цим ми додамо 10 тестових записів! Завантажте наступну URL-адресу:

http://VASH-DOMEN/index.php/complexworld/index/populateEntries

 

Якщо ви подивитеся на свою базу даних, ви повинні побачити 10 нових рядків у таблиці eavblog_posts. А також 10 нових рядків у таблиці eavblog_posts_varchar.

Зверніть увагу, що eavblog_posts_varchar пов’язане з eavblog_posts стовпцем entity_id.

 

Нарешті, давайте витягнемо дані нашої Моделі. Завантажте в браузері наступну URL-адресу:

http://VASH-DOMEN/index.php/complexworld/index/showCollection

 

Це має дати нам помилку:

Warning: include(Alanstormdotcom/Complexworld/Model/Resource/Eavblogpost/Collection.php) [function.include]: failed to open stream: No such file or directory in /lib/Varien/Autoload.php on line 93

 

Так близько! Ми не створили клас для об’єкта колекції! На щастя, це так само просто, як і для звичайної Моделі Ресурсів. Додайте наступний файл із таким вмістом:

 

Файл: Alanstormdotcom/Complexworld/Model/Resource/Eavblogpost/Collection.php:

class Alanstormdotcom_Complexworld_Model_Resource_Eavblogpost_Collection extends Mage_Eav_Model_Entity_Collection_Abstract {
  protected function _construct() {
     $this->_init('complexworld/eavblogpost');
  }
}

 

Це лише стандартний метод _construct Magento для ініціалізації моделі. Після цього перезавантажте сторінку, і ви повинні побачити всі заголовки та контент постів. Але зверніть увагу, що значення дати відсутнє!

 

 

Які атрибути у вибірці?

Якщо ви уважно дивилися на код в контролері, ви могли помітити дещо інший вигляд завантаження колекції:

 

$entries = $weblog2->getCollection()
  ->addAttributeToSelect('title')
  ->addAttributeToSelect('content');

 

Оскільки запити EAV даних можуть бути досить SQL надмірними, вам потрібно буде вказувати лише ті атрибути у вибірці, які потрібні для ваших Моделей. Таким чином, система буде робити лише ті запити, які їй дійсно потрібні. Якщо ж вам не шкода ресурсів свого серверу, ви можете використовувати «дикий» код для вибірки всіх наявних атрибутів:

 

$entries = $weblog2->getCollection()->addAttributeToSelect('*');

 

 

 

Підсумок

Розуміючи це, ви зможете витягувати з бази даних лише потрібну інформацію, або ж будете знати, чому інформація певних атрибутів не показується у вашому інтернет-магазині.

Є ще багато чого, що вам потрібно знати про EAV. Нижче представлено перелік деяких тем, які я б хотів розкрити більш детально, і які можливо будуть обговорені в наступних статтях:

 

  1. EAV Атрибути: Атрибути не обмежуються типами datetime, decimal, int, text та varchar. Ви можете створити власні файли класів, щоб змоделювати різні атрибути. У цьому вам допоможе властивість сутності attribute_model.
  2. Фільтрація колекції: фільтрація колекції EAV даних може бути складною справою, особливо якщо ви працюєте з вищезгаданими непростими атрибутами. Перед завантаженням колекції вам потрібно використовувати метод addAttributeToFilter.
  3. Ієрархія Magento EAV: Magento взяв основну Модель EAV і створив ієрархію, яка дуже тісно пов’язана з функціональністю магазину, а також містить стратегію зменшення кількості запитів, що генерує модель EAV.

 

Моделі EAV, без сумніву, є найбільш складною частиною системи Magento, з якою повинен мати справу розробник сайтів для електронної комерції. Не забувайте глибоко дихати і в кінці дня згадуйте, що це і є програмування. Все відбувається з конкретної причини, вам потрібно лише з’ясувати, з якої.

 

 

 

Автор: Alan Storm (http://alanstorm.com/magento_advanced_orm_entity_attribute_value_part_1/)

Переклад українською: Ненько Сергій

Адаптація перекладу: SebWeo

 
 

 

Recent Posts

Чи можна знайти доступний хостинг у 2024 році?

Якщо ви плануєте розмістити веб-сайт в мережі Інтернет, дуже важливо знайти для нього швидкий і…

23 години ago

Чому обрати освіту за кордоном: переваги для майбутнього вашої дитини

Навчання за кордоном вже давно асоціюється з якісною освітою, новими можливостями та безліччю перспектив. Але…

3 дні ago

Як вибрати майстра для перетяжки меблів?

Вибір майстра для ремонту та перетяжки меблів – завдання, яке потребує вдумливого підходу. Адже від…

4 дні ago

Що краще вибрати для хостингу: сервер VPS Windows чи VPS Linux?

Вибір ідеального хостингу під свій сайт може бути досить заплутаною справою, особливо коли існує багато…

2 тижні ago

Лоуренс Пітер

Щоб уникати помилок, потрібно набиратися досвіду; щоб набиратися досвіду, потрібно робити помилки Лоуренс Пітер  

2 тижні ago

Що таке Чорне СЕО (Black Hat SEO) — вся потрібна інформація

Коротке визначення Чорного SEO Чорне СЕО (або Чорна оптимізація) — це будь-яка практика, метою якої…

2 тижні ago