在Magento中有三中产品关系:Up-sells, Related Products,和Cross-sell Products。最近在讨论客户需求的时候,我们发现在Magento中创建独立的自定义产品关系能更好地实现我们的目的。在这篇文章中,我将演示如何增加自定义的Magento产品关系. 简介下面,我将用Magento插件中的代码来说明一下在Magento中添加自定义产品关系的过程。 安装脚本程序首先,要让Magento数据库知道我们新的产品链接类型。以下是安装脚本: app/code/community/Alwayly/CustomLinkedProducts/sql/alwayly_customlinkedproducts_setup/install-0.0.1.php <?php $installer = $this; /** * Install product link types */ $data = array( array( 'link_type_id' => Alwayly_CustomLinkedProducts_Model_Catalog_Product_Link::LINK_TYPE_CUSTOM, 'code' => 'custom' ) ); foreach ($data as $bind) { $installer->getConnection()->insertForce($installer->getTable('catalog/product_link_type'), $bind); } /** * Install product link attributes */ $data = array( array( 'link_type_id' => Alwayly_CustomLinkedProducts_Model_Catalog_Product_Link::LINK_TYPE_CUSTOM, 'product_link_attribute_code' => 'position', 'data_type' => 'int' ) ); $installer->getConnection()->insertMultiple($installer->getTable('catalog/product_link_attribute'), $data); 后台界面下一步就是在后台产品信息页添加新标签。下面是相关的PHP代码,稍后我们会用我们的XML文件将它添加到布局。 app/code/community/Alwayly/CustomLinkedProducts/Block/Adminhtml/Catalog/Product/Edit/Tab.php <?php class Alwayly_CustomLinkedProducts_Block_Adminhtml_Catalog_Product_Edit_Tab extends Mage_Adminhtml_Block_Widget implements Mage_Adminhtml_Block_Widget_Tab_Interface { public function canShowTab() { return true; } public function getTabLabel() { return $this->__('Custom Linked Products'); } public function getTabTitle() { return $this->__('Custom Linked Products'); } public function isHidden() { return false; } public function getTabUrl() { return $this->getUrl('*/*/custom', array('_current' => true)); } public function getTabClass() { return 'ajax'; } } 因为我们的标签指向‘*/*/custom’路由,所以我们需要将它添加到Mage_Adminhtml_Catalog_ProductController。以下是代码: app/code/community/Alwayly/CustomLinkedProducts/controllers/Adminhtml/Catalog/ProductController.php <?php require_once(Mage::getModuleDir('controllers','Mage_Adminhtml').DS.'Catalog'.DS.'ProductController.php'); class Alwayly_CustomLinkedProducts_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Catalog_ProductController { /** * Get custom products grid and serializer block */ public function customAction() { $this->_initProduct(); $this->loadLayout(); $this->getLayout()->getBlock('catalog.product.edit.tab.custom') ->setProductsCustom($this->getRequest()->getPost('products_custom', null)); $this->renderLayout(); } /** * Get custom products grid */ public function customGridAction() { $this->_initProduct(); $this->loadLayout(); $this->getLayout()->getBlock('catalog.product.edit.tab.custom') ->setProductsRelated($this->getRequest()->getPost('products_custom', null)); $this->renderLayout(); } } 为了将我们的新标签添加到后台,也为了getBlock(‘catalog.product.edit.tab.custom’)方法能作用于customAction()和customGridAction()。我们需要在我们的布局里添加一点XML代码。 <?xml version="1.0" encoding="UTF-8"?> <layout> <adminhtml_catalog_product_edit> <reference name="product_tabs"> <action method="addTab"> <name>custom</name> <block>alwayly_customlinkedproducts/adminhtml_catalog_product_edit_tab</block> </action> </reference> </adminhtml_catalog_product_edit> <adminhtml_catalog_product_custom> <block type="core/text_list" name="root" output="toHtml"> <block type="alwayly_customlinkedproducts/adminhtml_catalog_product_edit_tab_custom" name="catalog.product.edit.tab.custom"/> <block type="adminhtml/widget_grid_serializer" name="custom_grid_serializer"> <reference name="custom_grid_serializer"> <action method="initSerializerBlock"> <grid_block_name>catalog.product.edit.tab.custom</grid_block_name> <data_callback>getSelectedCustomProducts</data_callback> <hidden_input_name>links[custom]products_custom 接着我们要为我们的自定义产品关系标签创建一个网格,让它可以在后台显示。这有大量的代码,但大部分都是些基础的代码。唯一你所要注意的是在_prepareCollection()功能中使用useCustomLinks()。下面是代码: <?php class Alwayly_CustomLinkedProducts_Block_Adminhtml_Catalog_Product_Edit_Tab_Custom extends Mage_Adminhtml_Block_Widget_Grid { /** * Set grid params * */ public function __construct() { parent::__construct(); $this->setId('custom_product_grid'); $this->setDefaultSort('entity_id'); $this->setUseAjax(true); if ($this->_getProduct()->getId()) { $this->setDefaultFilter(array('in_products' => 1)); } if ($this->isReadonly()) { $this->setFilterVisibility(false); } } /** * Retirve currently edited product model * * @return Mage_Catalog_Model_Product */ protected function _getProduct() { return Mage::registry('current_product'); } /** * Add filter * * @param object $column * @return Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Custom */ protected function _addColumnFilterToCollection($column) { // Set custom filter for in product flag if ($column->getId() == 'in_products') { $productIds = $this->_getSelectedProducts(); if (empty($productIds)) { $productIds = 0; } if ($column->getFilter()->getValue()) { $this->getCollection()->addFieldToFilter('entity_id', array('in' => $productIds)); } else { if($productIds) { $this->getCollection()->addFieldToFilter('entity_id', array('nin' => $productIds)); } } } else { parent::_addColumnFilterToCollection($column); } return $this; } /** * Prepare collection * * @return Mage_Adminhtml_Block_Widget_Grid */ protected function _prepareCollection() { $collection = Mage::getModel('catalog/product_link')->useCustomLinks() ->getProductCollection() ->setProduct($this->_getProduct()) ->addAttributeToSelect('*'); if ($this->isReadonly()) { $productIds = $this->_getSelectedProducts(); if (empty($productIds)) { $productIds = array(0); } $collection->addFieldToFilter('entity_id', array('in' => $productIds)); } $this->setCollection($collection); return parent::_prepareCollection(); } /** * Checks when this block is readonly * * @return boolean */ public function isReadonly() { return $this->_getProduct()->getCustomReadonly(); } /** * Add columns to grid * * @return Mage_Adminhtml_Block_Widget_Grid */ protected function _prepareColumns() { if (!$this->isReadonly()) { $this->addColumn('in_products', array( 'header_css_class' => 'a-center', 'type' => 'checkbox', 'name' => 'in_products', 'values' => $this->_getSelectedProducts(), 'align' => 'center', 'index' => 'entity_id' )); } $this->addColumn('entity_id', array( 'header' => Mage::helper('catalog')->__('ID'), 'sortable' => true, 'width' => 60, 'index' => 'entity_id' )); $this->addColumn('name', array( 'header' => Mage::helper('catalog')->__('Name'), 'index' => 'name' )); $this->addColumn('type', array( 'header' => Mage::helper('catalog')->__('Type'), 'width' => 100, 'index' => 'type_id', 'type' => 'options', 'options' => Mage::getSingleton('catalog/product_type')->getOptionArray(), )); $sets = Mage::getResourceModel('eav/entity_attribute_set_collection') ->setEntityTypeFilter(Mage::getModel('catalog/product')->getResource()->getTypeId()) ->load() ->toOptionHash(); $this->addColumn('set_name', array( 'header' => Mage::helper('catalog')->__('Attrib. Set Name'), 'width' => 130, 'index' => 'attribute_set_id', 'type' => 'options', 'options' => $sets, )); $this->addColumn('status', array( 'header' => Mage::helper('catalog')->__('Status'), 'width' => 90, 'index' => 'status', 'type' => 'options', 'options' => Mage::getSingleton('catalog/product_status')->getOptionArray(), )); $this->addColumn('visibility', array( 'header' => Mage::helper('catalog')->__('Visibility'), 'width' => 90, 'index' => 'visibility', 'type' => 'options', 'options' => Mage::getSingleton('catalog/product_visibility')->getOptionArray(), )); $this->addColumn('sku', array( 'header' => Mage::helper('catalog')->__('SKU'), 'width' => 80, 'index' => 'sku' )); $this->addColumn('price', array( 'header' => Mage::helper('catalog')->__('Price'), 'type' => 'currency', 'currency_code' => (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE), 'index' => 'price' )); $this->addColumn('position', array( 'header' => Mage::helper('catalog')->__('Position'), 'name' => 'position', 'type' => 'number', 'validate_class' => 'validate-number', 'index' => 'position', 'width' => 60, 'editable' => !$this->_getProduct()->getCustomReadonly(), 'edit_only' => !$this->_getProduct()->getId() )); return parent::_prepareColumns(); } /** * Rerieve grid URL * * @return string */ public function getGridUrl() { return $this->getData('grid_url') ? $this->getData('grid_url') : $this->getUrl('*/*/customGrid', array('_current' => true)); } /** * Retrieve selected custom products * * @return array */ protected function _getSelectedProducts() { $products = $this->getProductsCustom(); if (!is_array($products)) { $products = array_keys($this->getSelectedCustomProducts()); } return $products; } /** * Retrieve custom products * * @return array */ public function getSelectedCustomProducts() { $products = array(); foreach (Mage::registry('current_product')->getCustomProducts() as $product) { $products[$product->getId()] = array('position' => $product->getPosition()); } return $products; } } Magento后台中管理自定义产品关系的界面是这样的:
后端支持代码正如你注意到的,useCustomLinks()方法在catalog/product_link模型中是不存在的。因此,我们需要重写这个模型来添加我们自定义产品关系的功能。 app/code/community/Alwayly/CustomLinkedProducts/Model/Catalog/Product/Link.php <?php class Alwayly_CustomLinkedProducts_Model_Catalog_Product_Link extends Mage_Catalog_Model_Product_Link { const LINK_TYPE_CUSTOM = 6; /** * @return Mage_Catalog_Model_Product_Link */ public function useCustomLinks() { $this->setLinkTypeId(self::LINK_TYPE_CUSTOM); return $this; } /** * Save data for product relations * * @param Mage_Catalog_Model_Product $product * @return Mage_Catalog_Model_Product_Link */ public function saveProductRelations($product) { parent::saveProductRelations($product); $data = $product->getCustomLinkData(); if (!is_null($data)) { $this->_getResource()->saveProductLinks($product, $data, self::LINK_TYPE_CUSTOM); } } } 如果你想要在同一个Magento项目中再添加一个自定义关系,那么你需要增加LINK_TYPE_CUSTOM类常量来避免冲突。现在,你也许注意到catalog/product中没有getCustomLinkData()功能。别怕,下面这段代码能解决这个问题: app/code/community/Alwayly/CustomLinkedProducts/Model/Catalog/Product.php <?php class Alwayly_CustomLinkedProducts_Model_Catalog_Product extends Mage_Catalog_Model_Product { /** * Retrieve array of custom products * * @return array */ public function getCustomProducts() { if (!$this->hasCustomProducts()) { $products = array(); $collection = $this->getCustomProductCollection(); foreach ($collection as $product) { $products[] = $product; } $this->setCustomProducts($products); } return $this->getData('custom_products'); } /** * Retrieve custom products identifiers * * @return array */ public function getCustomProductIds() { if (!$this->hasCustomProductIds()) { $ids = array(); foreach ($this->getCustomProducts() as $product) { $ids[] = $product->getId(); } $this->setCustomProductIds($ids); } return $this->getData('custom_product_ids'); } /** * Retrieve collection custom product * * @return Mage_Catalog_Model_Resource_Product_Link_Product_Collection */ public function getCustomProductCollection() { $collection = $this->getLinkInstance()->useCustomLinks() ->getProductCollection() ->setIsStrongMode(); $collection->setProduct($this); return $collection; } /** * Retrieve collection custom link * * @return Mage_Catalog_Model_Resource_Product_Link_Collection */ public function getCustomLinkCollection() { $collection = $this->getLinkInstance()->useCustomLinks() ->getLinkCollection(); $collection->setProduct($this); $collection->addLinkTypeIdFilter(); $collection->addProductIdFilter(); $collection->joinAttributes(); return $collection; } } 还有一件重要的事情要完成:保存我们的产品关系并让它作用于产品。我们需要粘贴catalog_product_prepare_save和catalog_model_product_duplicate事件。下面是回调了这些事件的观察员类。 <?php class Alwayly_CustomLinkedProducts_Model_Observer extends Varien_Object { public function catalogProductPrepareSave($observer) { $event = $observer->getEvent(); $product = $event->getProduct(); $request = $event->getRequest(); $links = $request->getPost('links'); if (isset($links['custom']) && !$product->getCustomReadonly()) { $product->setCustomLinkData(Mage::helper('adminhtml/js')->decodeGridSerializedInput($links['custom'])); } } public function catalogModelProductDuplicate($observer) { $event = $observer->getEvent(); $currentProduct = $event->getCurrentProduct(); $newProduct = $event->getNewProduct(); $data = array(); $currentProduct->getLinkInstance()->useCustomLinks(); $attributes = array(); foreach ($currentProduct->getLinkInstance()->getAttributes() as $_attribute) { if (isset($_attribute['code'])) { $attributes[] = $_attribute['code']; } } foreach ($currentProduct->getCustomLinkCollection() as $_link) { $data[$_link->getLinkedProductId()] = $_link->toArray($attributes); } $newProduct->setCustomLinkData($data); } } 前台界面为了在Magento前端展示我们自定义的产品关系,我把Magento’s related products块及相关模板文件复制到alwayly_customrelatedproducts/catalog_product_list_custom块。我们复制的相关产品块将使用我们定义的产品关系。下面是前端显示效果:
希望能对你的项目有所帮助。 (责任编辑:最模板) |