1

I previously used Danslo ApiImport in several of my Magento 1.9.X projects in combination with a cron job to import new products and update existing products with CSV files automatically/periodically.

I'm wondering if there is a similar free extension/module for Magento 2.X that offers the same basic import/update functionality of default Magento 2 product attributes (preferably with basic documentation on how to use it)?

Or if someone could help with an example script on how to load data from a CSV file and update product qty and price or a script to create new simple products?

  • Free? Not that I know of. We use CommerceExtensions' Import/Export which does the job. Expensive, though. Would like to know when you encounter a free extension or a free script that does the job. – Els den Iep Feb 19 '18 at 15:59
  • @ElsdenIep here you go – Lez Mar 5 '18 at 17:41
  • Thanks for the input! There is a way to include images of the product and the category to which it belongs that is not the default – Nanda May 30 '18 at 14:30
  • who can help me? How to import products with your image and categories from a .csv? @Lez – Dx7 Aug 7 '18 at 11:40
  • This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review – Jai Aug 7 '18 at 12:01
5

I made 2 scripts for updating products and importing new products, based on a few similar questions/answers I found on SME and my own research.

The solution is tested and works on Magento 2.2 (but probably works on 2.1.X as well).

The scripts work together with a manually set up cron job which calls them (for example every 5 mins -> this depends on specific shop needs).

For my needs, I set up the cron job to call a shell script every 5 mins, which calls these php scripts and archives the CSV files in a seperate folder for potential debugging purposes (which might be needed later) and deletes the archive files if they're older than 30 days.

Example CSV for updating price and qty

"sku","price","qty"
"test_sku1","100","10"
"test_sku2","123","12"

Script for updating product qty and price

$file = fopen('var/import/update.csv', 'r', '"'); // set path to the CSV file
if ($file !== false) {

    require __DIR__ . '/app/bootstrap.php';
    $bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);

    $objectManager = $bootstrap->getObjectManager();

    $state = $objectManager->get('Magento\Framework\App\State');
    $state->setAreaCode('adminhtml');

    // used for updating product info
    $productRepository = $objectManager->get('Magento\Catalog\Model\ProductRepository');

    // used for updating product stock
    $stockRegistry = $objectManager->get('Magento\CatalogInventory\Api\StockRegistryInterface');

    // add logging capability
    $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/import-update.log');
    $logger = new \Zend\Log\Logger();
    $logger->addWriter($writer);

    // enter the number of data fields you require the product row inside the CSV file to contain
    $required_data_fields = 3;

    $header = fgetcsv($file); // get data headers and skip 1st row

    while ( $row = fgetcsv($file, 3000, ",") ) {

        $data_count = count($row);
        if ($data_count < 1) {
            continue;
        }

        $data = array();
        $data = array_combine($header, $row);

        $sku = $data['sku'];
        if ($data_count < $required_data_fields) {
            $logger->info("Skipping product sku " . $sku . ". Not enough data to import.");
            continue;
        }

        $qty = trim($data['qty']);
        $price = trim($data['price']);

        echo 'Updating product SKU: '.$sku.', with Qty: '.$qty.' and Price:'.$price.'<br />';

        try {
            $product = $productRepository->get($sku);
        } 
        catch (\Exception $e) {
            $logger->info("Invalid product SKU: ".$sku);
            continue;
        }

        // You can set other product data with $product->setAttributeName() if you want to update more data
        if ($product->getPrice() != $price) {
            $product->setPrice($price) 
                    ->setStoreId(0) // this is needed because if you have multiple store views, each individual store view will get "Use default value" unchecked for multiple attributes - which causes issues.
                    ->save();
        }

        try {
            $stockItem = $stockRegistry->getStockItemBySku($sku);
        } 
        catch (\Exception $e) {
            $logger->info("Invalid stock for product SKU: ".$sku);
            continue;
        }

        if ($stockItem->getQty() != $qty) {
            $stockItem->setQty($qty);
            if ($qty > 0) {
                $stockItem->setIsInStock(1);
            }
            $stockRegistry->updateStockItemBySku($sku, $stockItem);
        }
    }
    fclose($file);
}

Example CSV for importing new products

"sku","name","description","short_description","price","qty"
"test-sku1","Test product name1","Test product description1","Test product short description1","100","20"
"test-sku2","Test product name2","Test product description2","Test product short description2","10","30"

Script for importing new products

$file = fopen('var/import/new.csv', 'r', '"'); // set path to the CSV file
if ($file !== false) {

    require __DIR__ . '/app/bootstrap.php';
    $bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);

    $objectManager = $bootstrap->getObjectManager();

    $state = $objectManager->get('Magento\Framework\App\State');
    $state->setAreaCode('adminhtml');

    // used for updating product stock - and it's important that it's inside the while loop
    $stockRegistry = $objectManager->get('Magento\CatalogInventory\Api\StockRegistryInterface');

    // add logging capability
    $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/import-new.log');
    $logger = new \Zend\Log\Logger();
    $logger->addWriter($writer);

    $header = fgetcsv($file); // get data headers and skip 1st row

    // enter the min number of data fields you require that the new product will have (only if you want to standardize the import)
    $required_data_fields = 3;

    while ( $row = fgetcsv($file, 3000, ",") ) {

        $data_count = count($row);
        if ($data_count < 1) {
            continue;
        }

        // used for setting the new product data
        $product = $objectManager->create('Magento\Catalog\Model\Product');         
        $data = array();
        $data = array_combine($header, $row);

        $sku = $data['sku'];
        if ($data_count < $required_data_fields) {
            $logger->info("Skipping product sku " . $sku . ", not all required fields are present to create the product.");
            continue;
        }

        $name = $data['name'];
        $description = $data['description'];
        $shortDescription = $data['short_description'];
        $qty = trim($data['qty']);
        $price = trim($data['price']);

        try {
            $product->setTypeId('simple') // type of product you're importing
                    ->setStatus(1) // 1 = enabled
                    ->setAttributeSetId(4) // In Magento 2.2 attribute set id 4 is the Default attribute set (this may vary in other versions)
                    ->setName($name)
                    ->setSku($sku)
                    ->setPrice($price)
                    ->setTaxClassId(0) // 0 = None
                    ->setCategoryIds(array(2, 3)) // array of category IDs, 2 = Default Category
                    ->setDescription($description)
                    ->setShortDescription($shortDescription)
                    ->setUrlKey($url_key) // you don't need to set it, because Magento does this by default, but you can if you need to
                    ->setWebsiteIds(array(1)) // Default Website ID
                    ->setStoreId(0) // Default store ID
                    ->setVisibility(4) // 4 = Catalog & Search
                    ->save();

        } catch (\Exception $e) {
            $logger->info('Error importing product sku: '.$sku.'. '.$e->getMessage());
            continue;
        }

        try {
            $stockItem = $stockRegistry->getStockItemBySku($sku);

            if ($stockItem->getQty() != $qty) {
                $stockItem->setQty($qty);
                if ($qty > 0) {
                    $stockItem->setIsInStock(1);
                }
                $stockRegistry->updateStockItemBySku($sku, $stockItem);
            }
        } catch (\Exception $e) {
            $logger->info('Error importing stock for product sku: '.$sku.'. '.$e->getMessage());
            continue;
        }
        unset($product);
    }
    fclose($file);
}

These are quick and "dirty" solutions which work well for simple shops and imports, but they would probably have to be adjusted according to the specific needs of each project.

For example for more complex (multistore) shops which import custom (non-default) product data - but the scripts are easily adjustible.

You can get any CSV data with $data['custom_attribute'] and set it for the product by using $product->setCustomAttribute($data['custom_attribute']).

  • can i use this script in Magento ver. 1.9.3.2? – bhavin thummar Mar 28 '18 at 7:07
  • No, this is only for Magento 2+. For Magento 1.9.X I suggest using this module: github.com/danslo/ApiImport. And you can set it up pretty much the same way as I suggested in this answer (import CSV via cron job). – Lez Mar 28 '18 at 7:11
  • how to add this module in my magento store and where i can see this feature please help me how to do it – bhavin thummar Mar 28 '18 at 10:08
  • @bhavinthummar you can read instructions on how to install the module on the link I gave you. If that's too complex for you, I suggest opening a new question so I or someone else can help you in detail. – Lez Mar 28 '18 at 11:58

protected by Community Nov 6 '18 at 20:05

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.