修改Magento默认Export Customers功能

Magento 1.x的Export功能可以很方便地对Customers的数据进行导出,但是存在几个不足(或者说不方便)的地方:

  1. 默认导出的 .CSV文件是以UTF-8格式编码的,而MS Excle是无法识别UTF-8编码的,所以导出的 .CSV文件直接在Excle中打开时中文会乱码,乱码不仅会导致中文单元格无法阅读, 而且会影响其它单元格,会使其它单元格错位

  2. 缺少subscriber_status的信息。subscriber_status是用来标识一个Customer是否愿意接收订阅消息(Newsletter),这个信息经常会用到,但很可惜原生Magento Export无法导出subscriber_status信息,因为subscriber_status信息仅仅是Newsletter表的一个Field,不是Customer的attribute。

上面列出的2个不足:

  其中第1条是可以通过文件转码的方式解决的,不需要修改程序,而且修改程序会比较复杂。具体做法是用txt打开下载好的.CVS文件,然后选择“另存为”,在“另存为”对话框的下方,会有选择编码格式的下拉菜单,将编码格式从UTF-8改为ANSI,然后保存即可解决乱码问题。

  第2条是需要修改程序才能解决的。首先来看一下Magento的Default Export是如何实现的:

    在后台的Export页面,通过Form的action(index.php/admin/export/export/key/......./)可以知道,Export请求是在一个名叫Export的Controller中的exportAction中完成的。

    通过在IDE中搜索ExportController.php这个文件名可以很快定位代码位置,主要的工作是在以下这两个代码片段中完成的:

    忽略上下不相关的代码:

 1 /**
 2      * Load data with filter applying and create file for download.
 3      *
 4      * @return Mage_ImportExport_Adminhtml_ExportController
 5      */
 6     public function exportAction()
 7     {
 8          ......
 9                 /** @var $model Mage_ImportExport_Model_Export */
10                 $model = Mage::getModel('importexport/export');
11                 $model->setData($this->getRequest()->getParams());
12 
13                 return $this->_prepareDownloadResponse(
14                     $model->getFileName(),
15                     $model->export(),
16                     $model->getContentType()
17                 );
18          ......  
19     }

    $this->_prepareDownloadResponse($fileName, $content, $contentType = 'application/octet-stream', $contentLength = null)方法是Mage_Core_Controller_Varien_Action 类提供的封装好的方法,它根据参数中提供的文件名、文件内容、文件类型生成一个文件并发送到浏览器,这是一个公用的方法,我们只需要修改传给它的参数就可以修改Magento导出用户(Export customers)功能。

    我现在要给导出的.CSV文件添加subscriber_status项,也就是修改传给_prepareDownloadResponse()方法的第2个参数$model->export():

    具体思路:首先修改$collection,让$collection包含customers的subscriber_status数据

1 $collection->getSelect()->joinLeft(
2     array('ns' => 'newsletter_subscriber'),
3     'ns.customer_id = e.entity_id',
4     'ns.subscriber_status'
5 );

    然后在$row数组中添加subscriber_status数据: 

1 $row['subscribe_status'] = $this->getSubscriberLabel($item);

    其中, $this->getSubscriberLabel($item) 是新增的用来将subscriber_status转为容易阅读的label的方法:

 1 protected function getSubscriberLabel($item)
 2 {
 3     $subscriberStatus = (int)$item->getSubscriberStatus();
 4     if(!empty($subscriberStatus)){
 5         switch($subscriberStatus){
 6             case 1: return 'Subscribed';
 7             case 2: return 'Not_Active';
 8             case 3: return 'Unsubscribed';
 9             case 4: return 'Unconfirmed';
10             default: return null;
11         }
12     }
13     return null;
14 }

    别忘记添加表头:

1 // create export file
2 $writer->setHeaderCols(array_merge(
3     array('subscribe_status'),
4     $this->_permanentAttributes, $validAttrCodes,
5     array('password'), $addrColNames,
6     array_keys($defaultAddrMap)
7 ));

    最终修改后的export()方法(修改过或者新增的代码用红色标出):

  1 /**
  2  * Export process.
  3  *
  4  * @return string
  5  */
  6 public function export()
  7 {
  8     $collection     = $this->_prepareEntityCollection(Mage::getResourceModel('customer/customer_collection'));
  9     $validAttrCodes = $this->_getExportAttrCodes();
 10     $writer         = $this->getWriter();
 11     $defaultAddrMap = Mage_ImportExport_Model_Import_Entity_Customer_Address::getDefaultAddressAttrMapping();
 12 
 13     // prepare address data
 14     $addrAttributes = array();
 15     $addrColNames   = array();
 16     $customerAddrs  = array();
 17 
 18     foreach (Mage::getResourceModel('customer/address_attribute_collection')
 19                  ->addSystemHiddenFilter()
 20                  ->addExcludeHiddenFrontendFilter() as $attribute) {
 21         $options  = array();
 22         $attrCode = $attribute->getAttributeCode();
 23 
 24         if ($attribute->usesSource() && 'country_id' != $attrCode) {
 25             foreach ($attribute->getSource()->getAllOptions(false) as $option) {
 26                 foreach (is_array($option['value']) ? $option['value'] : array($option) as $innerOption) {
 27                     if (strlen($innerOption['value'])) { // skip ' -- Please Select -- ' option
 28                         $options[$innerOption['value']] = $innerOption['label'];
 29                     }
 30                 }
 31             }
 32         }
 33         $addrAttributes[$attrCode] = $options;
 34         $addrColNames[] = Mage_ImportExport_Model_Import_Entity_Customer_Address::getColNameForAttrCode($attrCode);
 35     }
 36     foreach (Mage::getResourceModel('customer/address_collection')->addAttributeToSelect('*') as $address) {
 37         $addrRow = array();
 38 
 39         foreach ($addrAttributes as $attrCode => $attrValues) {
 40             if (null !== $address->getData($attrCode)) {
 41                 $value = $address->getData($attrCode);
 42 
 43                 if ($attrValues) {
 44                     $value = $attrValues[$value];
 45                 }
 46                 $column = Mage_ImportExport_Model_Import_Entity_Customer_Address::getColNameForAttrCode($attrCode);
 47                 $addrRow[$column] = $value;
 48             }
 49         }
 50         $customerAddrs[$address['parent_id']][$address->getId()] = $addrRow;
 51     }
 52 
 53     // create export file
 54     $writer->setHeaderCols(array_merge(
 55         array('subscribe_status'),
 56         $this->_permanentAttributes, $validAttrCodes,
 57         array('password'), $addrColNames,
 58         array_keys($defaultAddrMap)
 59     ));
 60 
 61     $collection->getSelect()->joinLeft(
 62         array('ns' => 'newsletter_subscriber'),
 63         'ns.customer_id = e.entity_id',
 64         'ns.subscriber_status'
 65     );
 66     foreach ($collection as $itemId => $item) { // go through all customers
 67         $row = array();
 68 
 69         // go through all valid attribute codes
 70         foreach ($validAttrCodes as $attrCode) {
 71             $attrValue = $item->getData($attrCode);
 72 
 73             if (isset($this->_attributeValues[$attrCode])
 74                 && isset($this->_attributeValues[$attrCode][$attrValue])
 75             ) {
 76                 $attrValue = $this->_attributeValues[$attrCode][$attrValue];
 77             }
 78             if (null !== $attrValue) {
 79                 $row[$attrCode] = $attrValue;
 80             }
 81         }
 82         $row[self::COL_WEBSITE] = $this->_websiteIdToCode[$item['website_id']];
 83         $row[self::COL_STORE]   = $this->_storeIdToCode[$item['store_id']];
 84         $row['subscribe_status'] = $this->getSubscriberLabel($item); 86 
 87         // addresses injection
 88         $defaultAddrs = array();
 89 
 90         foreach ($defaultAddrMap as $colName => $addrAttrCode) {
 91             if (!empty($item[$addrAttrCode])) {
 92                 $defaultAddrs[$item[$addrAttrCode]][] = $colName;
 93             }
 94         }
 95         if (isset($customerAddrs[$itemId])) {
 96             while (($addrRow = each($customerAddrs[$itemId]))) {
 97                 if (isset($defaultAddrs[$addrRow['key']])) {
 98                     foreach ($defaultAddrs[$addrRow['key']] as $colName) {
 99                         $row[$colName] = 1;
100                     }
101                 }
102                 $writer->writeRow(array_merge($row, $addrRow['value']));
103 
104                 $row = array();
105             }
106         } else {
107             $writer->writeRow($row);
108         }
109     }
110     return $writer->getContents();
111 }

    建议不要直接修改Magento Default的代码,例如上面所做的修改,可以通过重写Magento Model的方法来实现。

如果您觉得阅读本文对您有帮助,欢迎转载本文,但是转载文章之后必须在文章页面明显位置保留此段声明,否则保留追究法律责任的权利。

作  者:blog.jpdou.top

原文链接:http://blog.jpdou.top/modify-magento-default-export-customers/

原文地址:https://www.cnblogs.com/jpdoutop/p/Magento-Customers-Export.html