Возможно ли получить объект-модель из нескольких таблиц?

[10 ноября 2016 г.]    Российская сборка Magento 2.49.12
Magento 2: модули и услуги
#1 Dante
  • Группа: Пользователь
  • Сообщений: 7
  • Регистрация: 03.06.2011

04.06.2011 20:48

Всем привет. Несколько абстрактный вопрос.
Я начинаю разбираться, поэтому за косноязычие простите.
Делаем модуль. Например блог, где пользователи могут оставлять свои записи.
Или чат, или новости, etc.
Пока воспользовались moduleCreator-ом.
Мы можем получить объект-модель из бд, коллекцию объектов.
$chat = Mage::getModel('chat/chat')->load($chat_id)->getData();

можем ее менять и сохранять в БД, без ручных sql запросов. Это хорошо)

А можем получить просто массив...
           	$resource = Mage::getSingleton('core/resource');
			$read= $resource->getConnection('core_read');
			$chatTable = $resource->getTableName('chat');
			
			$select = $read->select()
			   ->from($chatTable,array('chat_id','title','content','status'))
			   ->where('status',1)
			   ->order('created_time DESC') ;

Но вот нам надо связаться с другой таблицей, customer_entity, что бы вытянуть email пользователя.
Массив мы можем получить сложным запросом объединив несколько таблиц.
Объект мы можем получить как раньше, а email вторым запросом.
Как рациональней?
Возможно ли получить объект-модель из нескольких таблиц?

#2 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

04.06.2011 21:16

Можно.
Многие стандартные модели хранят данные в нескольких таблицах.

#3 vinnc
  • Группа: Пользователь
  • Сообщений: 7
  • Регистрация: 20.05.2011

06.06.2011 10:28

В магенте также можно делать join'ы :rolleyes: чтобы вытягивать данные из других таблиц с добавлением в коллекцию
 $collection = Mage::getModel('testing/test') -> getCollection();
        $collection -> getSelect()    -> join(array('product_cat' => 'catalog_product_entity_varchar'), 'main_table.product_id = product_cat.entity_id', array('product_cat.value'))
                        -> where('product_cat.attribute_id = 56');


#4 Dante
  • Группа: Пользователь
  • Сообщений: 7
  • Регистрация: 03.06.2011

14.06.2011 20:58

Конкретизируем задачу.

Задача: Мы добавляем таблицу, связанную с пользователем. Пусть это будет чат.
В таблице chat хранятся сообщения пользователя. Связь по id пользователя, конечно же. Связь типа один(пользователь) ко многим (сообщениям). Нам надо выдернуть все данные пользователя с новыми данными в один запрос.

Варианты:
1) Мы конечно же можем писать вручную километровый sql запрос. Например, след. запрос достает только имя пользователя:
$resource = Mage::getSingleton('core/resource');
$read = $resource->getConnection('core_read');
        $select = $read->select()
                ->from(array('chat' => $resource->getTableName('chat')), array('chat_id', 'chat.content','chat.created_at'))
                ->joinInner(array('cev' => $resource->getTableName('customer_entity_varchar')),
                            'chat.customer_id = cev.entity_id',
                            array('cev.value as customer_fullname'))
                ->joinInner(array('ea'=> $resource->getTableName('eav_attribute')),
                            'cev.attribute_id = ea.attribute_id',
                            null)
                ->where('ea.attribute_code = ?', 'firstname')
                ->where('chat.chat_id > ?', $id)
                ->distinct()


2) А хочеться воспользоваться готовой коллекцией пользователя, и не вникая, как работает eav customer-a, получить коллекцию, включающую новую связанную таблицу (chat).
2.1) Пляшем от модели customer. Т.е объединяем коллекцию пользователя с нашей таблицей:
 $collection = Mage::getModel('customer/customer')->getCollection();
 $select = $collection->addAttributeToSelect('*')->getSelect()->join('chat', "entity_id = chat.customer_id",
 array('chat_id','content','customer_id'))->distinct();
 $query = $select->__toString();
 $data = $collection->load($query);

Если бы отношение между таблицей и коллекцией было 1 к 1, то все было бы супер. Т.е. если в таблице чата у одного пользователя нету 2-х и более сообщений, то мы получаем все данные пользователя и данные таблицы в виде коллекции.
Проблема, когда на одного пользователя несколько сообщений. Тогда sql-запрос возвращает для каждого сообщения строку с данными пользователя, что не катит для коллекции. Для создания коллекции должена быть одна строка для одного пользователя. Иначе ошибка, мол, пользователь такой уже существует в коллекции.
2.2) Пляшем от модели чата. А к модели чата мы не можем(?) добавить модель customer-а, а потаблично нам не интересно, ибо тот же километровый sql запрос.

Вопрос: как все-таки получить все данные пользователя вкупе с данными подключаемой таблицы (для соотношения 1 ко многим)?

#5 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

14.06.2011 23:26

Я рекомендую два дополняющих друг друга способа ускорения извлечения разнородных данных из базы данных Magento.

  • Создать свой класс-индексатор, который будет проводить денормализацию разнородных данных в единую таблицу, оптимизированную для конкретных запросов.
    Так, в частности, делает ядро Magento для товаров, а я - для своего модуля Промо-подарки.

  • Реализовать индивидуальный алгоритм кеширования для своих нестандартных экранных блоков с учётом конкретных особенностей конкретной предметной области.


#6 Dante
  • Группа: Пользователь
  • Сообщений: 7
  • Регистрация: 03.06.2011

15.06.2011 07:46

Спасибо, будем разбираться.

#7 Дмитрий Федюк
  • Администратор
  • Иконка
  • Группа: Администратор
  • Сообщений: 8884
  • Регистрация: 20.02.2010

03.07.2011 08:46

Как автоматически загружать в модель данные сразу из нескольких таблиц

Поделиться темой: