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.
    – mark
    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;
    }
}

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.