如何循环 Magento 集合?

发布于 2024-09-24 22:27:51 字数 1408 浏览 4 评论 0原文

基本上,我需要获取客户的 CSV 文件,该文件每天在脚本中自动生成。 我尝试了几种方法,但它们太慢或者实际上耗尽了内存。

*1) foreach 通过集合资源 *

$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() . ",";
}

有什么想法吗?

谢谢!

Basically, I need to get a CSV file of my customers, generated automatically in a script every day.
I've tried several ways, but they are too slow or actually exhausted of memory.

*1) foreach through collection resource *

$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 and load customer

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

Any ideas?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

单调的奢华 2024-10-01 22:27:51

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

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

我们使用与此类似的方法从我们的商店导出订单。
我插入了你的收藏,它似乎有效。

<?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。

然后设置您的 cron 任务来运行:
php -f /path/to/your/magento/exportCustomers.php

Try paging a large collection!

The idea is if you can load the collection in smaller chunks, you won't use as much memory.
Load a chunk(page), then do something with it like saving it out to a text file and then load the next chunk. The result being, you've worked with the whole larger collection, but only incurred the memory cost of the largest page.

We use something similar to this to export orders from our store.
I plugged in your collection and it seems to work.

<?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";
?>

I saved it as exportCustomers.php.

Then setup your cron task to run:
php -f /path/to/your/magento/exportCustomers.php

合约呢 2024-10-01 22:27:51

在每个 Customer 对象上使用 load()显着减慢您的代码速度。我建议您将所需属性添加到集合中的第一种方法是正确的方法,但可以用以下方法完成:

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

这样,永远不会加载单个客户,而是 toArray() (< a href="http://docs.magentocommerce.com/Varien/Varien_Data/Varien_Data_Collection.html#toArray" rel="nofollow noreferrer">doco here)将为您提供您想要的字段,然后您可以迭代在多维数组上生成逗号分隔的字符串。

或者,您可以尝试 $collection->toXml() 并使用 XML(如果您对此感到满意)。 Google 会向您指出 xml->csv 转换方法。

Using a load() on each Customer object will significantly slow down your code. I would suggest that your first approach of adding the required attributes to the collection is the right one, but finish it with something like:

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

That way, the individual customers are never loaded, but toArray() (doco here) will give you the fields you want, then you can iterate over the multi-dimensional array to produce your comma-separated string.

Alternatively, you could try $collection->toXml() and work with XML if you're comfortable with that. The Google will point you to xml->csv conversion methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文