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/