Magento 2 import export module give you the ability to implement it behavior(standard system export import) with simple xml and general adapter . Some point before stated :
A – For import you need create import.xml inside etc of your module
B : You can create just import without export
C : Standard place to show of your import module is form menu system→export or system→ import .
Download simple project from github
In this course we try to create our custom module for import customer group with class tax id ,
the table customer_group have 3 column customer_group_id,customer_group_code,tax_class_id ,
ou customer_group.csv will be like :
customer_group_code,tax_class_id
new group1,3
new group2,4
………………….
1 - Implement import.xml:
First for all you need create import.xml inside etc folder in your module (Example module Ibnab/Tutie)
etc/import.xml :
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_ImportExport:etc/import.xsd"> <entity name="customer_group" label="Customer Group" model="Ibnab\Tutie\Model\Import\CustomerGroup" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Basic" /> </config>
now if you from menu to system→ import you will finding input select (with label Entity Type
) you will find as option added Entity Type but before using you need create your model adapter (Ibnab\Tutie\Model\Import\CustomerGroup) with second step.
1 - Create your model adapter:
Inside folder Model create folder Import and inside it create class CustomerGroup.php and fill :
<?php namespace Ibnab\Tutie\Model\Import; use Ibnab\Tutie\Model\Import\CustomerGroup\RowValidatorInterface as ValidatorInterface; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; class CustomerGroup extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity { const TITLE = 'customer_group_code'; const TAX = 'tax_class_id'; const TABLE_Entity = 'customer_group'; /** * Validation failure message template definitions * * @var array */ protected $_messageTemplates = [ ValidatorInterface::ERROR_TITLE_IS_EMPTY => 'TITLE is empty', ]; protected $_permanentAttributes = [self::TITLE]; /** * If we should check column names * * @var bool */ protected $needColumnCheck = true; protected $groupFactory; /** * Valid column names * * @array */ protected $validColumnNames = [ self::TITLE, self::TAX, ]; /** * Need to log in import history * * @var bool */ protected $logInHistory = true; protected $_validators = []; /** * @var \Magento\Framework\Stdlib\DateTime\DateTime */ protected $_connection; protected $_resource; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ public function __construct( \Magento\Framework\Json\Helper\Data $jsonHelper, \Magento\ImportExport\Helper\Data $importExportData, \Magento\ImportExport\Model\ResourceModel\Import\Data $importData, \Magento\Framework\App\ResourceConnection $resource, \Magento\ImportExport\Model\ResourceModel\Helper $resourceHelper, \Magento\Framework\Stdlib\StringUtils $string, ProcessingErrorAggregatorInterface $errorAggregator, \Magento\Customer\Model\GroupFactory $groupFactory ) { $this->jsonHelper = $jsonHelper; $this->_importExportData = $importExportData; $this->_resourceHelper = $resourceHelper; $this->_dataSourceModel = $importData; $this->_resource = $resource; $this->_connection = $resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION); $this->errorAggregator = $errorAggregator; $this->groupFactory = $groupFactory; } /** * Entity type code getter. * * @return string */ public function getEntityTypeCode() { return 'customer_group'; } /** * Row validation. * * @param array $rowData * @param int $rowNum * @return bool */ { $title = false; return !$this->getErrorAggregator()->isRowInvalid($rowNum); } $this->_validatedRows[$rowNum] = true; // BEHAVIOR_DELETE use specific validation logic // if (\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE == $this->getBehavior()) { $this->addRowError(ValidatorInterface::ERROR_TITLE_IS_EMPTY, $rowNum); return false; } return !$this->getErrorAggregator()->isRowInvalid($rowNum); } /** * Create Advanced price data from raw data. * * @throws \Exception * @return bool Result of operation. */ protected function _importData() { if (\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE == $this->getBehavior()) { $this->deleteEntity(); } elseif (\Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE == $this->getBehavior()) { $this->replaceEntity(); } elseif (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND == $this->getBehavior()) { $this->saveEntity(); } return true; } /** * Save newsletter subscriber * * @return $this */ public function saveEntity() { $this->saveAndReplaceEntity(); return $this; } /** * Replace newsletter subscriber * * @return $this */ public function replaceEntity() { $this->saveAndReplaceEntity(); return $this; } /** * Deletes newsletter subscriber data from raw data. * * @return $this */ public function deleteEntity() { $listTitle = []; while ($bunch = $this->_dataSourceModel->getNextBunch()) { foreach ($bunch as $rowNum => $rowData) { $this->validateRow($rowData, $rowNum); if (!$this->getErrorAggregator()->isRowInvalid($rowNum)) { $rowTtile = $rowData[self::TITLE]; $listTitle[] = $rowTtile; } if ($this->getErrorAggregator()->hasToBeTerminated()) { $this->getErrorAggregator()->addRowToSkip($rowNum); } } } if ($listTitle) { } return $this; } /** * Save and replace newsletter subscriber * * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function saveAndReplaceEntity() { $behavior = $this->getBehavior(); $listTitle = []; while ($bunch = $this->_dataSourceModel->getNextBunch()) { $entityList = []; foreach ($bunch as $rowNum => $rowData) { if (!$this->validateRow($rowData, $rowNum)) { $this->addRowError(ValidatorInterface::ERROR_TITLE_IS_EMPTY, $rowNum); continue; } if ($this->getErrorAggregator()->hasToBeTerminated()) { $this->getErrorAggregator()->addRowToSkip($rowNum); continue; } $rowTtile= $rowData[self::TITLE]; $listTitle[] = $rowTtile; $entityList[$rowTtile][] = [ self::TITLE => $rowData[self::TITLE], self::TAX => $rowData[self::TAX], ]; } if (\Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE == $behavior) { if ($listTitle) { $this->saveEntityFinish($entityList, self::TABLE_Entity); } } } elseif (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND == $behavior) { $this->saveEntityFinish($entityList, self::TABLE_Entity); } } return $this; } /** * Save product prices. * * @param array $priceData * @param string $table * @return $this */ { if ($entityData) { $tableName = $this->_connection->getTableName($table); $entityIn = []; foreach ($entityData as $id => $entityRows) { foreach ($entityRows as $row) { $entityIn[] = $row; } } if ($entityIn) { $this->_connection->insertOnDuplicate($tableName, $entityIn,[ self::TITLE, self::TAX ]); } } return $this; } { if ($table && $listTitle) { try { $this->countItemsDeleted += $this->_connection->delete( $this->_connection->getTableName($table), $this->_connection->quoteInto('customer_group_code IN (?)', $listTitle) ); return true; } catch (\Exception $e) { return false; } } else { return false; } } }
Some important technical explains:
const TITLE = 'customer_group_code'; const TAX = 'tax_class_id'; const TABLE_Entity = 'customer_group';
here we declare or constants columns and TABLE_Entity form where we deleting and inserting .
protected $validColumnNames = [ self::TITLE, self::TAX, ];
is check the system check if the header of csv is like this or no in validColumnNames or no .
public function getEntityTypeCode() { return 'customer_group'; }
return the same code inside your import.xml name="customer_group" .
{ $title = false; return !$this->getErrorAggregator()->isRowInvalid($rowNum); } $this->_validatedRows[$rowNum] = true; // BEHAVIOR_DELETE use specific validation logic // if (\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE == $this->getBehavior()) { $this->addRowError(ValidatorInterface::ERROR_TITLE_IS_EMPTY, $rowNum); return false; } return !$this->getErrorAggregator()->isRowInvalid($rowNum); }
we validate the current row with this line here just simple test if is empty .
The rest functions is implemented for insert update and delete.
Don't forget to add our Ibnab\Tutie\Model\Import\CustomerGroup\RowValidatorInterfac as ValidatorInterface used inside function validateRow and fill it with :
<?php /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ namespace Ibnab\Tutie\Model\Import\CustomerGroup; interface RowValidatorInterface extends \Magento\Framework\Validator\ValidatorInterface { const ERROR_INVALID_TITLE= 'InvalidValueTITLE'; const ERROR_TITLE_IS_EMPTY = 'EmptyTITLE'; /** * Initialize validator * * @return $this */ public function init($context); }
Comments