1

I am new in magento 2

I am trying to import product data programmatically using csv file.

The Error is shown below

enter image description here

My Folder and code structure are following.

This is My registration file.

Vendor/Modulename/regis.xml


use \Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(ComponentRegistrar::MODULE, 'vendorName_moduleName', __DIR__);

This is my module.xml file

Vendor/Modulename/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="VendoreName_ModuleName" setup_version="1.0.0"></module>
</config>

This is cron script file Crontab.php

Vendor/Modulename/etc/crontab.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <group id="importproduct">
        <job instance="VendorName\ModuleName\Cron\Test" method="execute" name="VendorName_ModuleName_cron">
            <schedule>5 0 26 8 4</schedule>
        </job>
    </group>
</config>

This is cron script file Test.php

Vendor/Modulename/Cron/Test.php


Class Test{
    $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

    $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);
}
}
1
  • Your class should have execute method and put all code in execute method. also check php -l Test.php for grammatically mistake
    – Pawan
    Aug 26, 2022 at 15:20

1 Answer 1

1

Import product data programmatically using CSV- file.

Step 1 : create a custom module. Example : WebbyTroops_ProductSync

Step 2 : Create custom cron :

Add crontab.xml file to define new cron tab, path WebbyTroops/ProductSync/etc/crontab.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
    <group id="default">
        <job name="import_products" instance="WebbyTroops\ProductSync\Cron\ImportProducts" method="execute">
        <schedule>*/5 * * * *</schedule>
        </job>
    </group>
</config>

Add cron Class to execute : WebbyTroops/ProductSync/Cron/ImportProducts.php

<?php

namespace WebbyTroops\ProductSync\Cron;

use Magento\ImportExport\Model\Import\Adapter;
use Magento\Framework\Filesystem;
use Magento\Framework\App\Filesystem\DirectoryList;

class ImportProducts
{
    /**
     * Import field separator.
     */
    const FIELD_FIELD_SEPARATOR = '_import_field_separator';

    /**
     * @var \WebbyTroops\ProductSync\Model\Import\Product
     */
    protected $productImport;

    /**
     * @var \Magento\Framework\Filesystem\DirectoryList
     */
    protected $directoryManager;

    /**
     * @var \Magento\ImportExport\Model\Import $import
     */
    protected $import;

    /**
     * @var Filesystem
     */
    protected $filesystem;

    /**
     * @var \Psr\Log\LoggerInterface
     */
    protected $logger;

    /**
     * @param \WebbyTroops\ProductSync\Model\Import\Product $productImport
     * @param \Magento\Framework\Filesystem\DirectoryList $directoryManager
     * @param \Magento\ImportExport\Model\Import $import
     * @param Filesystem $filesystem
     * @param \Psr\Log\LoggerInterface $logger
     */
    public function __construct(
        \WebbyTroops\ProductSync\Model\Import\Product $productImport,
        \Magento\Framework\Filesystem\DirectoryList $directoryManager,
        \Magento\ImportExport\Model\Import $import,
        Filesystem $filesystem,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->productImport = $productImport;
        $this->directoryManager = $directoryManager;
        $this->import = $import;
        $this->filesystem = $filesystem;
        $this->logger = $logger;
    }

    /**
     * @param \Magento\Framework\Event\Observer $observer
     * @return void
     */
    public function execute()
 {
        try {
            $varDirectory = $this->directoryManager->getPath('var');
            $productCsvFileName = "product-csv";

            $file = $varDirectory . DIRECTORY_SEPARATOR . $productCsvFileName . '.csv';

            $postData = [
                'entity' => 'catalog_product',
                'behavior' => 'append',
                'validation_strategy' => 'validation-stop-on-errors',
                'allowed_error_count' => 1,
                '_import_field_separator' => '',
                '_import_multiple_value_separator' => '',
                '_import_empty_attribute_value_constant' => '__EMPTY__VALUE__',
                'import_images_file_dir' => $varDirectory . '/import/images'
            ];

            $this->import->setData($postData);
            $source = $this->_getSourceAdapter($file);
            $isValid = $this->import->validateSource($source);

            if ($isValid) {
                $this->productImport->startImport($varDirectory . '/import/sync');
            } else {
                $errros = $this->import->getErrorAggregator()->getAllErrors();
                $this->logger->info(count($errros) . 'error(s) found while importing products from Vend.');
                foreach ($errros as $error) {
                    $this->logger->error($error->getErrorMessage() . ' at row number ' . $error->getRowNumber() . ' and coloumn name ' . $error->getColumnName());
                }
            }
        } catch (\Exception $e) {
            $this->logger->info('Something went wrong while importing products');
            $this->logger->error($e->getMessage());
        }
        return $this;
    }

    /**
     * Returns source adapter object.
     *
     * @param string $sourceFile Full path to source file
     * @return AbstractSource
     * @throws FileSystemException
     */
    protected function _getSourceAdapter($sourceFile)
    {
        return Adapter::findAdapterFor(
            $sourceFile,
            $this->filesystem->getDirectoryWrite(DirectoryList::ROOT),
            $this->import->getData(self::FIELD_FIELD_SEPARATOR)
        );
    }
}

Add product Import Class : path WebbyTroops/ProductSync/Model/Import/Product.php file :

<?php
declare(strict_types=1);

namespace WebbyTroops\ProductSync\Model\Import;

use Magento\Customer\Api\Data\CustomerInterface;
use Magento\ImportExport\Model\Import;
use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface;
use Magento\ImportExport\Model\Import\AbstractSource;
use Magento\Customer\Model\Indexer\Processor;
use Magento\Framework\App\ObjectManager;

/**
 * Product Import
 *
 */
class Product
{

    /**
     * @var \Magento\ImportExport\Model\Import
     */
    protected $import;

    /**
     * @var \Magento\ImportExport\Model\Import\ImageDirectoryBaseProvider
     */
    protected $imagesDirProvider;

    /**
     * @var \WebbyTroops\ProductSync\Logger\Logger
     */
    protected $logger;

    /**
     * @param \Magento\ImportExport\Model\Import $import
     * @param \Magento\ImportExport\Model\Import\ImageDirectoryBaseProvider $imageDirectoryBaseProvider
     * @param \WebbyTroops\ProductSync\Logger\Logger $logger
     */
    public function __construct(
        \Magento\ImportExport\Model\Import $import,
        \Magento\ImportExport\Model\Import\ImageDirectoryBaseProvider $imageDirectoryBaseProvider,
        \WebbyTroops\ProductSync\Logger\Logger $logger
    ) {
        $this->import = $import;
        $this->imagesDirProvider = $imageDirectoryBaseProvider;
        $this->logger = $logger;
    }

    public function startImport($imagePath)
    {
        $data = [
            'entity' => 'catalog_product',
            'behavior' => 'append',
            'validation_strategy' => 'validation-stop-on-errors',
            'allowed_error_count' => 1,
            '_import_field_separator' => '',
            '_import_multiple_value_separator' => '',
            '_import_empty_attribute_value_constant' => '__EMPTY__VALUE__',
            'import_images_file_dir' => ''

        ];
        $this->import->setData($data);
        //Images can be read only from given directory.
        $this->import->setData('images_base_directory', $this->imagesDirProvider->getDirectory());
        $errorAggregator = $this->import->getErrorAggregator();
        $errorAggregator->initValidationStrategy(
            $this->import->getData(Import::FIELD_NAME_VALIDATION_STRATEGY),
            $this->import->getData(Import::FIELD_NAME_ALLOWED_ERROR_COUNT)
        );
        try {
            $this->import->importSource();
        } catch (\Exception $e) {
            $this->logger->info('Something went wrong while importing products');
            $this->logger->error($e->getMessage());
        }
    }
}

Note : You should put your CSV file in var directory with name product-csv.csv and CSV format will as usual default magento 2 sample format.

Hope it's useful.

Thank You!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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