2012-03-05 108 views
4

3个模型映射3个表格:Image,Slider和SliderImageAssoc。在这种情况下,它是一对多的,因为一个图像可以“链接”到许多滑块。我熟悉的ZF方式也提出了3种模型,并且在其中存储特殊的内部数据时,可以执行像$ imageRow-> getSliderViaSliderImageAssoc()这样的操作,从而生成滑块的父级行某些Image模型。自定义Magento模型之间的多对多或一对多关系

我的问题是如何确切地提取Magento中的相关模型?我见过名为setParentFieldName的方法,但我不认为它们是核心的。你可以做这样的事情:

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

PS:我不一定要使用ZF风格的抓取。

回答

7

就我所知,在Magento中不支持实体表关系的通用映射。我建议在资源模型和资源集合中添加辅助方法,以根据需要将选择对象添加到选择对象中。

下面是来自所提及的工具方法方法的核心的实例来加载在收集的附加数据:

// 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; 
} 

如果调用,core_url_rewrite表与产品实体表接合。

如果每次都需要加载加入的数据,则_getLoadSelect()方法可用于资源模型,或_initSelect()用于收集。
下面是从cms/page资源模型的例子:

// 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; 
} 

_initSelect()一个例子联接可在Mage_CatalogInventory_Model_Resource_Stock_Item_Collection::_initSelect()发现(我就不会在这里发布它,因为它是如此的相似例如_getLoadSelect())。

某些模块设置来自模块“外部”的集合的连接,即库存项目集合Mage_CatalogInventory_Model_Resource_Stock_Item::addCatalogInventoryToProductCollection($productCollection)。这里cataloginventory模块使用产品集合选择对象来添加一些连接的数据。

最后,另一种方法是加载所需要的数据在_afterLoad()方法做单独的选择(相比于加入):

// 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(); 
} 

这可以使用一个*_load_after事件也做了集合或楷模。

+0

您能否更具体地了解在核心中哪里可以找到这些示例? – nevvermind 2012-03-05 13:00:32

+0

增加了答案的例子。 – Vinai 2012-03-05 15:23:16

+0

非常好。谢谢。 – nevvermind 2012-03-05 15:52:17