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

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

 

На диаграмме представлена ​​грубая схема таблиц базы данных 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_group, eav_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

 
 

Все статьи данной серии:

  1. Magento для PHP MVC разработчиков (Alan Storm) – ч.1/11
  2. Magento для PHP MVC разработчиков – разбор контроллера (ч.2/11)
  3. Magento для PHP MVC разработчиков – Макеты, Блоки и Шаблоны (ч.3/11)
  4. Magento для PHP MVC разработчиков – Модели и основы ORM (ч.4/11)
  5. Magento для PHP MVC разработчиков – Инсталлирование Ресурса (ч.5/11)
  6. Magento для PHP MVC разработчиков – Расширенный ORM – EAV (ч.6/11)
  7. Magento для PHP MVC разработчиков – Особая конфигурация системы (ч.7/11)
  8. Magento для PHP MVC разработчиков – Углубленная настройка системы (ч.8/11)
  9. Magento для PHP MVC разработчиков – Коллекции Varien Data (ч.9/11)
  10. Magento для PHP MVC разработчиков – Переопределение и обновляемость системы (ч.10/11)
  11. Magento для PHP MVC разработчиков – Конфигурация системы по умолчанию (ч.11/11)

 



Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *