1

I want to make module that creates magento products from xml file. So I have module with command php bin/magento LCB:import path/to/xml. It loads xml file with custom attributes which need to be created. I know how create attribute via InstallData.php or UpgradeData.

I need

$eavSetup->addAttribute() 

function in my Model. Is it even possible to extend Model in this way?

I didn't found anything useful in my case. Below is my code. I have errors in:

 $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); 

The problem is that:

$eavSetup requeres $setup

$setup requires $resource

$resource requires something with Interface and so on... still doesn't work

Code:

namespace LCB\Import\Model; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; use Magento\Framework\Setup\UpgradeDataInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\ModuleDataSetupInterface; use Magento\Framework\Module\Setup; use Magento\Framework\App\ResourceConnection; use Magento\Setup\Module\Setup\ResourceConfig; use Magento\Setup\Module\ConnectionFactory; use magento\framework\App\DeploymentConfig; use magento\framework\App\DeploymentConfig\Reader; use Magento\Framework\App\Filesystem\DirectoryList; use magento\framework\Config\File\ConfigFilePool; use magento\framework\Filesystem\DriverPool; class Importer { private $eavSetupFactory; private $objectManager; public function __construct() { $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $this->eavSetupFactory = new EavSetupFactory($this->objectManager); } public function createAttribute($attributes) { $dirList = new DirectoryList(BP); $driverPool = new DriverPool(); $configFilePool = new ConfigFilePool(); $Reader = new Reader($dirList, $driverPool, $configFilePool); $DeploymentConfig = new DeploymentConfig($Reader); $ConnectionFactory = new ConnectionFactory(); $ResourceConfig = new ResourceConfig(); $resource = new ResourceConnection($ResourceConfig, $ConnectionFactory, $DeploymentConfig); $setup = new Setup($resource); $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); foreach ($attributes as $attribute){ $eavSetup->addAttribute( \Magento\Catalog\Model\Product::ENTITY, $attribute, [ 'type' => 'text', 'backend' => '', 'frontend' => '', 'label' => $attribute, 'input' => '', 'class' => '', 'source' => '', 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL, 'visible' => true, 'required' => false, 'user_defined' => false, 'default' => '', 'searchable' => false, 'filterable' => false, 'comparable' => false, 'visible_on_front' => false, 'used_in_product_listing' => true, 'unique' => false, 'apply_to' => '' ] ); } } } 

Main question is:

How to implement addAttribute() function from eav in my Model or it is not possible?

Edit:

@B G Kavinga I tried to do like this even earlier. Let try this way. I type command LCB:import then execute() function from my command class is called. In this function new Importer is created then I need to call createAttribute();

If not in createAttribute() function, I need to create eavSetup in my Command Class when I create new Impoter. So I need to create $eavSetupFactory, $setup and $setup requires ModuleDataSetupInterface and so on...

I need to create whole $eavSetupFactory properly. Which requires a lot od dependencies. So I need to create about 20 or even more "new" objects (I guess it is not a good practice). So how to implement this $eavSetupFactory in a right way?

Here is the mentioned execute function:

class ImportCommand extends Command { protected function execute(InputInterface $input, OutputInterface $output) { $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $eavSetupFactory = new EavSetupFactory($objectManager); $context = new Context(); //Context requires a lot of dependencies and dependencies requires other too $setup = new DataSetup($context); //requires ModuleDataSetupInterface $Importer = new Importer($eavSetupFactory, $setup); //load attributes $Importer->createAttribute($attributes); } } 

2 Answers 2

2

Do not use the new keyword to create an object, instead inject required object using the constructor. Read http://devdocs.magento.com/guides/v2.0/extension-dev-guide/depend-inj.html Try following code:

<?php namespace BGKavinga\Examples\Model; use Magento\Eav\Setup\EavSetup; use Magento\Eav\Setup\EavSetupFactory; use Magento\Framework\Setup\ModuleDataSetupInterface; class Importer { /** * @var ModuleDataSetupInterface */ private $setup; /** * Init * * @param EavSetupFactory $eavSetupFactory * @param ModuleDataSetupInterface $setup */ public function __construct(EavSetupFactory $eavSetupFactory, ModuleDataSetupInterface $setup) { $this->eavSetupFactory = $eavSetupFactory; $this->setup = $setup; } /** * @param $attributes */ public function createAttribute($attributes) { /** @var EavSetup $eavSetup */ $eavSetup = $this->eavSetupFactory->create(['setup' => $this->setup]); foreach ($attributes as $attribute) { $eavSetup->addAttribute( \Magento\Catalog\Model\Product::ENTITY, $attribute, [ 'type' => 'text', 'backend' => '', 'frontend' => '', 'label' => $attribute, 'input' => '', 'class' => '', 'source' => '', 'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL, 'visible' => true, 'required' => false, 'user_defined' => false, 'default' => '', 'searchable' => false, 'filterable' => false, 'comparable' => false, 'visible_on_front' => false, 'used_in_product_listing' => true, 'unique' => false, 'apply_to' => '' ] ); } } 

}

Check module here. https://github.com/bgkavinga/sample-code/raw/master/magento2-create-product-attributes.tar.gz

1
  • Thank you for the answer but still cant use it. If you can check my question again I've added some more info. Commented Apr 24, 2017 at 9:31
0

@B G Kavinga thank you, your answer brought me on right way. I don't know if it is good solution but it works for me. I just added to my ImportCommand constructor like this.

use LCB\Import\Model\Importer; class ImportCommand extends Command { private $importer; public function __construct(Importer $importer) { parent::__construct(); $this->importer = $importer; } } 

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.