Many-to-Many or One-to-Many Relationships Between Custom Magento Models

3 models displaying 3 tables: image, slider, and ImageAssoc slider. In this case, it is one-to-many, since a single image can be β€œlinked” to many sliders.

In the ZF method I'm used to, 3 models are also offered, and with special internal data stored in them, you can do things like $ imageRow-> getSliderViaSliderImageAssoc (), resulting in the Slider parent line of this specific image model .

My question is, how exactly do you choose related models in Magento? I saw methods called setParentFieldName , but I don’t think they were in the kernel. Can you do something like:

 foreach ($model->getCollection() as $model) { $parentRow = $model->getParent('some/model/name'); $dependentRowset = $model->getChildren('some/other/model/name'); } 

PS: I don't necessarily want to use the ZF style for extraction.

+4
source share
1 answer

Magento does not support general mapping of object table relationships, as far as I know. I suggest adding helper methods to the resource model and resource collection to add connections to the selected object, if necessary.

The following are examples from the main method of the mentioned utility method for loading additional data into a collection:

 // from Mage_Catalog_Model_Resource_Product_Collection::joinUrlRewrite() public function joinUrlRewrite() { $this->joinTable( 'core/url_rewrite', 'entity_id=entity_id', array('request_path'), '{{table}}.type = ' . Mage_Core_Model_Url_Rewrite::TYPE_PRODUCT, 'left' ); return $this; } 

If called, the core_url_rewrite table joins the product entity table.

If the combined data needs to be loaded every time, the _getLoadSelect() method can be used for resource models or _initSelect() for collections.
Here is an example of this from the cms/page resource model:

 // from Mage_Cms_Model_Resource_Page::_getLoadSelect() protected function _getLoadSelect($field, $value, $object) { $select = parent::_getLoadSelect($field, $value, $object); if ($object->getStoreId()) { $storeIds = array(Mage_Core_Model_App::ADMIN_STORE_ID, (int)$object->getStoreId()); $select->join( array('cms_page_store' => $this->getTable('cms/page_store')), $this->getMainTable() . '.page_id = cms_page_store.page_id', array()) ->where('is_active = ?', 1) ->where('cms_page_store.store_id IN (?)', $storeIds) ->order('cms_page_store.store_id DESC') ->limit(1); } return $select; } 

An example of combining _initSelect() can be found in Mage_CatalogInventory_Model_Resource_Stock_Item_Collection::_initSelect() (I will not post it here because it looks so much like the example of _getLoadSelect() ).

Some modules establish connections in collections from an "external" module, i.e. stock Mage_CatalogInventory_Model_Resource_Stock_Item::addCatalogInventoryToProductCollection($productCollection) collections Mage_CatalogInventory_Model_Resource_Stock_Item::addCatalogInventoryToProductCollection($productCollection) . Here, the cataloginventory module uses the product collection selection object to add some aggregated data.

Finally, another approach is to load the necessary data into the _afterLoad() method, which performs a separate selection (compared to the connection):

 // from Mage_Cms_Model_Resource_Page_Collection::_afterLoad() protected function _afterLoad() { if ($this->_previewFlag) { $items = $this->getColumnValues('page_id'); $connection = $this->getConnection(); if (count($items)) { $select = $connection->select() ->from(array('cps'=>$this->getTable('cms/page_store'))) ->where('cps.page_id IN (?)', $items); if ($result = $connection->fetchPairs($select)) { foreach ($this as $item) { if (!isset($result[$item->getData('page_id')])) { continue; } if ($result[$item->getData('page_id')] == 0) { $stores = Mage::app()->getStores(false, true); $storeId = current($stores)->getId(); $storeCode = key($stores); } else { $storeId = $result[$item->getData('page_id')]; $storeCode = Mage::app()->getStore($storeId)->getCode(); } $item->setData('_first_store_id', $storeId); $item->setData('store_code', $storeCode); } } } } return parent::_afterLoad(); } 

This can also be done using the *_load_after for collections or models.

+7
source

Source: https://habr.com/ru/post/1399752/


All Articles