Записать очень большой массив в файл на PHP - PullRequest
0 голосов
/ 06 сентября 2010

У меня есть клиент с магазином Magento.Они создают текстовый файл для загрузки в googlebase, который содержит все их продукты, но из-за количества продуктов (20 КБ) сценарий срывается, когда он занимает около 1 ГБ.Он запускается через cron.

Есть ли способ сжать или сегментировать массив, или записать его в файл по мере его создания, а не создавать массив и затем записывать его?

<?php
define('SAVE_FEED_LOCATION','/home/public_html/export/googlebase/google_base_feed_cron.txt');



set_time_limit(0);

require_once '/home/public_html/app/Mage.php';
    Mage::app('default');

try{
    $handle = fopen(SAVE_FEED_LOCATION, 'w');


    $heading = array('id','title','description','link','image_link','price','product_type','condition','c:product_code');
    $feed_line=implode("\t", $heading)."\r\n";
    fwrite($handle, $feed_line);

    $products = Mage::getModel('catalog/product')->getCollection();
    $products->addAttributeToFilter('status', 1);//enabled
    $products->addAttributeToFilter('visibility', 4);//catalog, search
    $products->addAttributeToFilter('type_id', 'simple');//simple only (until fix is made)
    $products->addAttributeToSelect('*');
    $prodIds=$products->getAllIds();

    foreach($prodIds as $productId) {

        $product = Mage::getModel('catalog/product'); 

        $product->load($productId);

        $product_data = array();
        $product_data['sku']=$product->getSku();
        $product_data['title']=$product->getName();
        $product_data['description']=$product->getShortDescription();
        $product_data['link']=$product->getProductUrl(). '?source=googleps';
        $product_data['image_link']=Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA).'catalog/product'.$product->getImage();

        // Get price of item
if($product->getSpecialPrice())
            $product_data['price']=$product->getSpecialPrice();
        else
   $product_data['price']=$product->getPrice();


        $product_data['product_type']='';
        $product_data['condition']='new';
        $product_data['c:product_code']=$product_data['sku'];


        foreach($product->getCategoryIds() as $_categoryId){
            $category = Mage::getModel('catalog/category')->load($_categoryId);
            $product_data['product_type'].=$category->getName().', ';
        }
        $product_data['product_type']=rtrim($product_data['product_type'],', ');



        //sanitize data
        foreach($product_data as $k=>$val){
        $bad=array('"',"\r\n","\n","\r","\t");
        $good=array(""," "," "," ","");
        $product_data[$k] = '"'.str_replace($bad,$good,$val).'"';
        }


        $feed_line = implode("\t", $product_data)."\r\n";
        fwrite($handle, $feed_line);
        fflush($handle);
    }

    //---------------------- WRITE THE FEED
    fclose($handle);

}
catch(Exception $e){
    die($e->getMessage());
}

?>

1 Ответ

0 голосов
/ 06 сентября 2010

У меня здесь два быстрых ответа:

1) Попробуйте увеличить максимально допустимый объем памяти php (для командной строки, так как это скрипт cron)

2) То, как старшие разработчики решают подобные проблемы, где я сейчас работаю, выглядит примерно так:

Создайте атрибут поля даты с именем, например googlebase_uploaded, и запустите скрипт cron с чем-то вроде const MAX_PRODUCTS_TO_WRITE. Затем добавьте файл и отметьте каждый продукт, который был добавлен.

То, что я пытаюсь сказать, это разделить время выполнения на более медленные куски, которые не нарушат сценарий.

К сожалению, вот где я скучаю по Java и C #

...