In the following article I would like to share my experience of Custom Product Type creation and I’d like to guide you how to import it to the system in specific way.
Sometimes we are facing some extraordinary needs of our clients about product types, and these types are easy to create by observer or default product types. But sometimes there is no way, except of creating your own type of product. For example it could be applied to gift cards or other types of VIP cards.
I won’t tell you about creating a new module from scratch (this info you can find from another source), so let’s get into the basic part:
Let’s say you’ve already created a module and the first thing we have to do is to add a file with description of a new type of product: <Vendor_Name>/<Module_Name>/etc/product_types.xml
Example:
1 2 3 |
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Catalog:etc/product_types.xsd"> <type name="my_new_product_type" label="My Product Type" modelInstance="Vendor_Name\Module_Name\Model\Product\Type"></type> </config> |
You can specify such attributes:
- name: new product code
- label: product name
- modelInstance: new product model
- indexPriority: priority index
- isQty: whether it has a quantity
- sortOrder: position number in sort list
- canUseQtyDecimals: whether the quantity is fractional
Also we are capable to override such internal models:
- priceModel: model of a price
- indexerModel: model of indexing logic
- stockIndexerModel: model of stock indexing
Example:
1 2 3 4 |
<type name="my_new_product_type"> <priceModel instance="Vendor_Name\Module_Name\Model\Product\Price" /> <indexerModel instance="Vendor_Name\Module_Name\Model\Product\Indexer" /> </type> |
Or we can add custom attributes:
Example:
1 2 3 4 5 |
<type name="my_new_product_type"> <customAttributes> <attribute name="is_special_product" value="true"/> </customAttributes> </type> |
So now let’s take a look at class content. First of all:
<Vendor_Name>\<Module_Name>\Model\Product\Type.php
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
namespace <Vendor_Name>\<Module_Name>\Model\Product; class Type extends \Magento\Catalog\Model\Product\Type\AbstractType { const TYPE_ID = ‘my_new_product_type’; public function save($product) { parent::save($product); // your additional saving logic return $this; } public function deleteTypeSpecificData(\Magento\Catalog\Model\Product $product) { //your deleting logic } } |
Custom model of the price:
<Vendor_Name>\<Module_Name>\Model\Product\Price.php
Example:
1 2 3 4 5 6 7 8 9 |
namespace <Vendor_Name>\<Module_Name>\Model\Product; class Price extends \Magento\Catalog\Model\Product\Type\Price { public function getPrice($product) { return 0; //add your logic here } } |
We created primary files for a new product. Now we should initialize it into the system. And for that we must describe process of installation of the module.
<Vendor_Name>\<Module_Name>\Setup\InstallData.php
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
namespace <Vendor_Name>\<Module_Name>\Setup; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; use Magento\Framework\Setup\InstallDataInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; class InstallData implements InstallDataInterface { private $eavSetupFactory; public function __construct(EavSetupFactory $eavSetupFactory) { $this->eavSetupFactory = $eavSetupFactory; } public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) { /** @var EavSetup $eavSetup */ $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); $fieldList = [ 'price', 'special_price', 'special_from_date', 'special_to_date', 'minimal_price', 'cost', 'tier_price', 'weight', ]; foreach ($fieldList as $field) { $applyTo = explode( ',', $eavSetup->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $field, 'apply_to') ); if (!in_array(‘my_new_product_type’, $applyTo)) { $applyTo[] = 'my_new_product_type'; $eavSetup->updateAttribute( \Magento\Catalog\Model\Product::ENTITY, $field, 'apply_to', implode(',', $applyTo) ); } } $applyTo = explode(',', $eavSetup->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'cost', 'apply_to')); unset($applyTo[array_search('my_new_product_type', $applyTo)]); $eavSetup->updateAttribute(\Magento\Catalog\Model\Product::ENTITY, 'cost', 'apply_to', implode(',', $applyTo)); } } |
Perfect! A new product is done. And now if you want to fill your store with new products, what should you do?
Partner With Us
Let's discuss how to grow your business. Get a Free Quote.Further I am going to describe a process of creating a custom import of our new products. First of all we must create the file:
<Vendor_Name>/<Module_Name>/etc/import.xml
1 2 3 |
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_ImportExport:etc/import.xsd"> <entityType entity="catalog_product" name="my_new_product_type" model="Vendor_Name\Module_Name\Model\Import\Type\MyProduct" /> </config> |
- entity: EAV import model
- name: import code
- model: data processing model
In the current xml file we describe import model and its relations, for example reindexing trigger after import.
Below is the import model that could be inherited by abstract class
\Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
namespace <Vendor_Name>\<Module_Name>\Model\Import\Type; class MyProduct extends \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType { /** * Delimiter before product option value. */ const BEFORE_OPTION_VALUE_DELIMITER = ';'; /** * Pair value separator. */ const PAIR_VALUE_SEPARATOR = '='; /** * Dynamic value. */ const VALUE_DYNAMIC = 'dynamic'; /** * Fixed value. */ const VALUE_FIXED = 'fixed'; /** * Not fixed dynamic attribute. */ const NOT_FIXED_DYNAMIC_ATTRIBUTE = 'price_view'; /** * Selection price type fixed. */ const SELECTION_PRICE_TYPE_FIXED = 0; /** * Selection price type percent. */ const SELECTION_PRICE_TYPE_PERCENT = 1; /** * Instance of database adapter. * * @var \Magento\Framework\DB\Adapter\AdapterInterface */ protected $connection; /** * Instance of application resource. * * @var \Magento\Framework\App\ResourceConnection */ protected $_resource; /** * Array of cached options. * * @var array */ protected $_cachedOptions = []; /** * Array of cached skus. * * @var array */ protected $_cachedSkus = []; /** * Mapping array between cached skus and products. * * @var array */ protected $_cachedSkuToProducts = []; /** * Array of queries selecting cached options. * * @var array */ protected $_cachedOptionSelectQuery = []; public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) { // Ваша логика return parent::isRowValid($rowData, $rowNum, $isNewProduct); } // your code could be here } |
Data export process looks rather similar. We describe export.xml file, it has the same content, but refer to export models and export class of our type.
Well, I think that’s all. Thanks for reading this brief guide and I hope it will be helpful in the process of creating new products and import.
Here is an example of the module.
Magento Development
Take your online store to the next level with BelVG Magento Development
Visit the page
Hi Nowsath
could you please contact [email protected] so we could make everything clear.
Notice: Use of undefined constant ‘my_new_product_type’ – assumed ‘‘my_new_product_type’’ in /var/www/html/xxxxxx/app/code/Webkul/Sellerproduct/Setup/InstallData.php on line 47
i am facing this kind of issues while upgrade…
Hi, Vishal! Thanks for your question.
COST attribute may not be reflected for a new type of product, but for this one there is a specific field price_my_type.
To manage apply_to option you can also implement our module https://store.belvg.com/apply-to-attribute-option-for-magento-2-0.html
Not Working Above example my COST attribute not display in admin.