如何循环遍历Magento集合?

4
基本上,我需要每天自动生成一个客户的CSV文件。我已经尝试了几种方法,但它们太慢或者实际上已经耗尽了内存。
*1)通过循环遍历集合资源 *
$collection = Mage::getResourceModel('customer/customer_collection')
->addAttributeToSelect('email')
->addAttributeToSelect('created_at')
->joinAttribute('billing_company', 'customer_address/company', 'default_billing', null, 'left')
->joinAttribute('billing_street', 'customer_address/street', 'default_billing', null, 'left')
->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
->joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left');

foreach($collection as $customer) {
echo $customer->getFirstname() . ",";
}

2) foreach和加载客户

$collection = Mage::getResourceModel('customer/customer_collection');
foreach($collection as $customer) {
  $fullcustomer = Mage::getModel("customer/customer")->load($customer->getId());
  echo $fullcustomer->getFirstname() . ",";
}

有什么想法吗?
谢谢!

这两种解决方案都似乎可行,但两者都不是特别理想。能否请您在帖子中更新这两种方法的问题,以便我们知道您需要什么? - Joe Mastey
尝试在Magento中使用资源迭代器。请参阅此帖子:http://stackoverflow.com/questions/7419886/using-magentos-resource-iterator-model-on-a-product-collection - awaage
2个回答

15

尝试对大型集合进行分页!

这个想法是,如果您可以将集合分成较小的块加载,那么就不会使用太多内存。 加载一个块(页面),然后执行一些操作,比如将其保存到文本文件中,然后加载下一个块。结果是,您已经处理了整个较大的集合,但只产生了最大页面的内存成本。

我们使用类似于此来从我们的商店导出订单。 我插入了您的集合,它似乎可以工作。

<?php

 if(php_sapi_name()!=="cli"){
 echo "Must be run from the command line.";
 };

/**
 * Setup a magento instance so we can run this export from the command line.
 */

require_once('app/Mage.php');
umask(0);

if (!Mage::isInstalled()) {
    echo "Application is not installed yet, please complete install wizard first.";
    exit;
}

// Only for urls // Don't remove this
$_SERVER['SCRIPT_NAME'] = str_replace(basename(__FILE__), 'index.php', $_SERVER['SCRIPT_NAME']);
$_SERVER['SCRIPT_FILENAME'] = str_replace(basename(__FILE__), 'index.php', $_SERVER['SCRIPT_FILENAME']);

Mage::app('admin')->setUseSessionInUrl(false);
Mage::setIsDeveloperMode(true); ini_set('display_errors', 1); error_reporting(E_ALL);

try {
    Mage::getConfig()->init();
    Mage::app();   
} catch (Exception $e) {
    Mage::printException($e);
}
ini_set('memory_limit','500M');

$customerCount = 0;
try{
    //configure the collection filters.
    $collection = Mage::getResourceModel('customer/customer_collection')
    ->addAttributeToSelect('email')
    ->addAttributeToSelect('created_at')
    ->joinAttribute('billing_company', 'customer_address/company', 'default_billing', null, 'left')
    ->joinAttribute('billing_street', 'customer_address/street', 'default_billing', null, 'left')
    ->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
    ->joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
    ->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
    ->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
    ->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left');

    //Add a page size to the result set.
    $collection->setPageSize(100);
    //discover how many page the result will be.
    $pages = $collection->getLastPageNumber();
    $currentPage = 1;
    //This is the file to append the output to.
    $fp = fopen('/tmp/customers.csv', 'w');
    do{
         //Tell the collection which page to load.
         $collection->setCurPage($currentPage);
         $collection->load();
         foreach ($collection as $customer){
            //write the collection array as a CSV.
            $customerArray = $customer->toArray();
            //var_dump($customerArray); echo "\n\n";
            fputcsv($fp, $customerArray);
            $customerCount++;
         }
         $currentPage++;
         //make the collection unload the data in memory so it will pick up the next page when load() is called.
         $collection->clear();
    } while ($currentPage <= $pages);
    fclose($fp);
} catch (Exception $e) {
    //$response['error'] = $e->getMessage();
    Mage::printException($e);
}
echo "Saved $customerCount customers to csv file \n";
?>

我已经把它保存为"exportCustomers.php"。
然后设置您的定时任务运行: php -f /path/to/your/magento/exportCustomers.php

分页集合绝对是最好的选择。它非常快速且更加内存高效。 - Corgalore
然而,我注意到使用它时,每个页面的处理时间比上一个页面要长。就好像collection->clear()没有真正释放内存或者其他问题正在发生一样。 - Corgalore

4

在每个客户对象上使用load()显著地减慢您的代码速度。我建议您采用第一种方法,将所需属性添加到集合中,但最好以以下方式完成:

$collection->toArray([$arrRequiredFields = array()]);

那样,个别客户永远不会被加载,但是 toArray() (这里有文档) 将为您提供所需的字段,然后您可以遍历多维数组以生成逗号分隔的字符串。
或者,如果您熟悉 XML,则可以尝试 $collection->toXml() 并使用 XML 进行操作。Google 将指向 xml->csv 转换方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接