Magento开发经验总结(一 初初见你——产品属性集搜索模块)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Magento开发经验总结(一 初初见你——产品属性集搜索模块)相关的知识,希望对你有一定的参考价值。

一、 初初见你——产品属性集搜索模块

         产品属性搜索模块作为我第一个开发的定制功能模块,对于我个人理解magento系统内部规则与机制、二次开发规则等具有极其重要的意义。可以这么说,通过此模块的开发,我轻轻叩开了magento系统开发的大门,第一次看到了门内复杂、深邃、丰富及灵活的运行机制。

         在门外徘徊的我感触良多,magento上手难这件事情我真真切切得感受到了,但是一旦入了门,我们可以从过程中学到非常多的东西,如深入理解设计模式、构建软件理论、模式设计、领域驱动设计等等。

         1. 功能需求:新创建商品时,由于产品属性集数量过多,选择相应的产品属性集造成了很大困难,所以需要增加一个产品属性集搜索功能;

技术分享

 

     2. 功能设计:

         方案一:修改属性集选择方式,从select下拉框变为radio单选按钮,将所有数据平铺在页面上,通过浏览器搜索页面内容来定位所要选择的属性集;

         方案二:增加一个input输入框,通过搜索关键字进行属性集选择;

         3. 方案分析:首先,方案一虽然可以完成我们想要完成的功能,但是将所有属性集平铺在页面上,使得页面内容过多、杂乱,显得有些蠢,用户界面不友好,所以我们选择方案二;其次,方案二可以通过Ajax方式搜索,也可以通过js代码搜索静态内容,在我们这种情况下,产品属性集数据已经被一次性取出,如果再使用Ajax方式搜索数据会增加系统不必要的开销,所以pass;最后,我们得出结论,使用输入框对静态数据进行搜索;

         4. 接下来我们需要分析所修改模块的运行机制,然后找到具体从何处入手,添加我们所需的功能;

    •  该页面地址为:example.com/index.php/admin/catalog_product/index/key /f69e5bd9dc6e01ad2ed4becc85a5f31ebda96f26429055d7e80b8333ccde0572/,其中 index/后的key字符串是系统的secret key,用来保障系统后台访问安全用的,在测试环境下可以将其关闭,路径为System|Configuration|Admin|Security;

      技术分享

    • 我们获得有效信息路径为/admin/catalog_product/index/,根据magento规则(其中magento具体规则请参看《magento学习手记》),我们可以得出,该路径的控制器为/code/core/Mage/Adminhtml/controllers/Catelog/ProductControllers.php中的newAction()方法,在该方法中我们可以看到正常的取数据、赋值、加载布局和渲染布局。
    • 根据magento的系统规则我们这时去Adminhtml模块中的config.xml去寻找对应的布局文件;

 

 1       <layout>
 2             <updates>
 3                 <adminhtml>
 4                     <file>main.xml</file>
 5                 </adminhtml>
 6                 <report>
 7                     <file>report.xml</file>
 8                 </report>
 9                 <catalog>
10                     <file>catalog.xml</file>
11                 </catalog>
12                 <customer>
13                     <file>customer.xml</file>
14                 </customer>
15                 <promo>
16                     <file>promo.xml</file>
17                 </promo>
18             </updates>
19         </layout>
20     

 

 

    • 与访问控制器比对Adminhtml/controllers/Catelog/ProductControllers.php,我们可以看到Adminhtml模块中的catalog部分的布局文件为catalog.xml;
    • catalog.xml文件路径为/app/design/adminhtml/default/default/layout/catalog.xml(根据magento前端布局规则),找到<adminhtml_catalog_product_new>标签,刚好对应相应控制器,代码如下:
 1 <adminhtml_catalog_product_new>
 2         <update handle="editor"/>
 3         <reference name="content">
 4             <block type="adminhtml/catalog_product_edit" name="product_edit"></block>
 5         </reference>
 6         <reference name="left">
 7             <block type="adminhtml/catalog_product_edit_tabs" name="product_tabs"></block>
 8         </reference>
 9         <reference name="js">
10             <block type="adminhtml/catalog_product_edit_js" template="catalog/product/js.phtml" name="catalog_product_js"></block>
11             <block type="core/template" template="catalog/wysiwyg/js.phtml"/>
12         </reference>    
13 </adminhtml_catalog_product_new>

 

    • 从上面代码中我们可以看出,其中引入了四个block;第一个catalog_product_edit是我们页面中最外层大的block,上面有Back、Reset等按钮及页面显示内容框架;第二个catalog_product_edit_tabs是左侧标签显示及其相关右侧内容块;第三和第四个都是引入js代码的块;
    • block标签中的type对应的是其引用的类,根据规则可以知道该路径为/Mage/Adminhtml/Block/Catalog/Product/Edit/Tabs.php,我们来看一下Mage_Adminhtml_Block_Catalog_Product_Edit_Tabs类中的代码,我们定位到_prepareLayout()方法,该方法为此block类渲染页面准备必要的配置和数据。在该方法的第187行,我们可以清楚的看到,当 setId为空时(即为创建新商品),setting tabs的内容页引用的类为adminhtml/catalog_product_edit_tab_settings;

 技术分享

 

    •  这时我们找到adminhtml/catalog_product_edit_tab_settings类的位置为/Mage/Adminhtml/Block/Catalog/Product/Edit/Tab/Settings.php,打开该文件,我们在_prepareForm()方法中看到页面加载的具体控件及数据,这时我们已经定位到我们做需要的位置,现在可以增加我们自己的内容;


 

         5. 接下来我们将用到Magento后台的通用组件Form,相关Form的widget请查阅《Magento学习手记》,其中有所有widget的详细用法。我们先分析一下_perpareForm()方法中的代码:

 

 1     protected function _prepareForm()
 2     {
 3         $form = new Varien_Data_Form();//创建Form对象
 4         $fieldset = $form->addFieldset(‘settings‘, array(‘legend‘=>Mage::helper(‘catalog‘)->__(‘Create Product Settings‘)));//设置Tab页标题
 5 
 6         $entityType = Mage::registry(‘product‘)->getResource()->getEntityType();//获取实例类型
 7 
 8         $fieldset->addField(‘attribute_set_id‘, ‘select‘, array(
 9             ‘label‘ => Mage::helper(‘catalog‘)->__(‘Attribute Set‘),
10             ‘title‘ => Mage::helper(‘catalog‘)->__(‘Attribute Set‘),
11             ‘name‘  => ‘set‘,
12             ‘value‘ => $entityType->getDefaultAttributeSetId(),
13             ‘values‘=> Mage::getResourceModel(‘eav/entity_attribute_set_collection‘)
14                 ->setEntityTypeFilter($entityType->getId())
15                 ->load()
16                 ->toOptionArray()
17         ));//设置Attributes set下拉框及相关内容
18 
19         $fieldset->addField(‘product_type‘, ‘select‘, array(
20             ‘label‘ => Mage::helper(‘catalog‘)->__(‘Product Type‘),
21             ‘title‘ => Mage::helper(‘catalog‘)->__(‘Product Type‘),
22             ‘name‘  => ‘type‘,
23             ‘value‘ => ‘‘,
24             ‘values‘=> Mage::getModel(‘catalog/product_type‘)->getOptionArray()
25         ));//设置Product Type下拉框及相关内容
26 
27         $fieldset->addField(‘continue_button‘, ‘note‘, array(
28             ‘text‘ => $this->getChildHtml(‘continue_button‘),
29         ));//设置按钮
30 
31         $this->setForm($form);//加载form
32     }

 

         6. 现在我们知道了要在在Attributes Set下拉框前增加一个input内容,这时我们考虑如何完成该事情。首先,肯定不能直接添加代码,原因有两条:第一、当magento系统升级时可能会覆盖我们所增加的功能代码;第二、除非是bug我们需要修改代码,如果是正常模块代码,直接修改将违背开放封闭原则,不利于代码维护及团队开发;所以,我们应该选择系统增加新模块扩展原更能模块,这样新模块可以基于被扩展模块增加新的功能,又不影响旧有模块的使用。

         7. 接下来我们在/code/local下新建YM命名空间,在新建一个Attributesetsearch模块(具体模块新建过程请查看《Magento学习手记》);

         8. 接下来我们考虑通过何种方式扩展原模块功能,magento系统提供类重写和事件监听机制进行功能扩展,其中具体差别和优缺点也可以查看《Magento学习手记》,此处,我们两种方式都可用,因为我们所需要重写的类Mage_Adminhtml_Block_Catalog_Product_Edit

_Tab_Settings没有子孙类,所以重写该类中的某个方法并不会影响到其他类的正常使用,另外,该类仅在Mage_Adminhtml_Block_Catalog_Product_Edit_Tabs类中被使用了一次,而这正是我们要改动扩展的地方,所以使用类重写的方式并不会影响系统中其他功能代码;

         9. 类的重写需要先配置我们新建模块的config.xml文件,配置类重写(配置类的重写规则请参考《Magento学习手记》中重写核心类实例),具体代码如下:

 

 1     <global>
 2         <blocks>
 3             <attributesetsearch>
 4                 <class>YEMA_Attributesetsearch_Block</class>
 5             </attributesetsearch>
 6             <adminhtml>
 7                 <rewrite>
 8                     <catalog_product_edit_tab_settings>YEMA_Attributesetsearch_Block_Catalog_Product_Edit_Tab_Settings</catalog_product_edit_tab_settings>
 9                 </rewrite>
10             </adminhtml>
11         </blocks>
12     </global>

 

 

         10. 此时我们根据规则创建/Attributesetsearch/Block/Catalog/Product/Edit/Tab/Setting.php文件,申明YM_Attributesetsearch_Block_Catalog_Product_Edit_Tab_Settings类,该类继承类Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Settings,将需要重写的方法拷贝复制到类主体中,具体代码如下:

 

 

 1 <?php
 2 class YEMA_Attributesetsearch_Block_Catalog_Product_Edit_Tab_Settings extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Settings{
 3     protected function _prepareForm()
 4     {
 5         $form = new Varien_Data_Form();
 6         $fieldset = $form->addFieldset(‘settings‘, array(‘legend‘=>Mage::helper(‘catalog‘)->__(‘Create Product Settings‘)));
 7     
 8         $entityType = Mage::registry(‘product‘)->getResource()->getEntityType();
 9     
10         $_jscode = "
11                 function search(val){
12                     if(val == ‘‘){
13                         resetAction();
14                     }else{
15                         resetAction();
16                         searchAction(val);
17                     }
18                 }
19                 function resetAction(){
20                     var options =\$A($(‘attribute_set_id‘).options).each(function(option){
21                         option.show();
22                     });
23                 }
24                 function searchAction(val){
25                     var options =\$A($(‘attribute_set_id‘).options).each(function(option){
26                         var keyword = new RegExp(val);
27                         var content = option.innerHTML;
28                         if(!keyword.test(content)){
29                             option.hide();
30                         }
31                     });
32                 }
33                 search($(this).value);
34                 ";
35         $fieldset->addField(‘attribute_set_search‘, ‘text‘, array(
36                 ‘label‘ => Mage::helper(‘catalog‘)->__(‘Attribute Set Search‘),
37                 ‘title‘ => Mage::helper(‘catalog‘)->__(‘Attribute Set Search‘),
38                 ‘name‘  => ‘search‘,
39                 ‘onchange‘=> $_jscode,
40         ));
41     
42         $fieldset->addField(‘attribute_set_id‘, ‘select‘, array(
43                 ‘label‘ => Mage::helper(‘catalog‘)->__(‘Attribute Set‘),
44                 ‘title‘ => Mage::helper(‘catalog‘)->__(‘Attribute Set‘),
45                 ‘name‘  => ‘set‘,
46                 ‘value‘ => $entityType->getDefaultAttributeSetId(),
47                 ‘values‘=> Mage::getResourceModel(‘eav/entity_attribute_set_collection‘)
48                 ->setEntityTypeFilter($entityType->getId())
49                 ->load()
50                 ->toOptionArray()
51         ));
52     
53         $fieldset->addField(‘product_type‘, ‘select‘, array(
54                 ‘label‘ => Mage::helper(‘catalog‘)->__(‘Product Type‘),
55                 ‘title‘ => Mage::helper(‘catalog‘)->__(‘Product Type‘),
56                 ‘name‘  => ‘type‘,
57                 ‘value‘ => ‘‘,
58                 ‘values‘=> Mage::getModel(‘catalog/product_type‘)->getOptionArray()
59         ));
60     
61         $fieldset->addField(‘continue_button‘, ‘note‘, array(
62                 ‘text‘ => $this->getChildHtml(‘continue_button‘),
63         ));
64     
65         $this->setForm($form);
66     }
67 }

 

 

         11. 这里我们在Attribute Set下拉框选项前,增加了一个Attribute Set Search输入框,通过该输入框可以控制Attribute Set下拉框显示内容,从而完成属性集搜索功能,我们使用了input中的onchange方法来触发我们搜索的js代码;这里需要注意的是,magento的后台没有引入jquery,虽然看起来有点儿像,其实我们这里使用的是prototype.js的语法规则。

 

 

 

 

 

 

 

以上是关于Magento开发经验总结(一 初初见你——产品属性集搜索模块)的主要内容,如果未能解决你的问题,请参考以下文章

初初见你,编程海洋里你独自美丽(叁)

请问 Magento某产品库存无货如何在前台继续显示?

设计模式之初见

产品开发经验总结-让你少奋斗一年的经验之谈

记录一次由屁股决定研发的狗血经历

如何实现Magento产品批量导入