1

I'm trying to ad a customer attribute outside a Setup Script.

To be more specific inside a console command using CustomerSetupFactory::updateAttribute method.

I get an error caused by DI.

Argument 1 passed to Magento\Setup\Module\DataSetup::__construct() must be an instance of Magento\Framework\Module\Setup\Context, instance of Magento\Framework\ObjectManager\ObjectManager given, called in /var/www/magento/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php on line 93 in /var/www/magento/setup/src/Magento/Setup/Module/DataSetup.php on line 57

Is there any reason why not to do what I'm trying to achieve?

Is there any way to fix my problem?

What I did

Cleared cache. Cleared var/generation and var/di manually. Ran setup:di:compile

Thanks

EDIT:

This works if:

1. Clear var/generation manually 

2. Do not run setup:di:compile and run my CLI Command

It does not work if setup:di:copile ran. I have to mention that setup:di:compile ran without error

What is causing this behavior is setup:di:compile at fault?

1
  • Can you paste the code here please, looks like it is parent constructor issue, where you don't add the parent constructor parameters in your class I guess. Thanks. Feb 9, 2018 at 12:51

1 Answer 1

3

I did following way and working fine with compile. You can try.

app/code/SR/Stackexchange/etc/di.xml


<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\Console\CommandList">
        <arguments>
            <argument name="commands" xsi:type="array">
                <item name="add_customer_attribute_command" xsi:type="object">SR\Stackexchange\Console\Command\AddCustomerAttribute</item>
            </argument>
        </arguments>
    </type>
</config>

app/code/SR/Stackexchange/Console/Command/AddCustomerAttribute.php


namespace SR\Stackexchange\Console\Command;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Output\OutputInterface;
use Magento\Customer\Model\Customer;
use Magento\Customer\Setup\CustomerSetup;
use \Magento\Framework\Setup\ModuleDataSetupInterface;

class AddCustomerAttribute extends Command
{
    /**
     * Customer setup factory
     *
     * @var \Magento\Customer\Setup\CustomerSetupFactory
     */
    private $customerSetupFactory;

    /**
     * @var ModuleDataSetupInterface
     */
    private $setup;

    /**
     * @var \Magento\Framework\App\State
     */
    private $appState;

    /**
     * @var \Symfony\Component\Console\Output\OutputInterface
     */
    private $output;

    /**
     * AddCustomerAttribute constructor.
     *
     * @param \Magento\Customer\Setup\CustomerSetupFactory $customerSetupFactory
     * @param ModuleDataSetupInterface $setup
     * @param \Magento\Framework\App\State $appState
     */
    public function __construct(
        \Magento\Customer\Setup\CustomerSetupFactory $customerSetupFactory,
        ModuleDataSetupInterface $setup,
        \Magento\Framework\App\State $appState
    ) {
        $this->customerSetupFactory = $customerSetupFactory;
        $this->setup = $setup;
        $this->appState = $appState;

        $this->appState->setAreaCode(\Magento\Framework\App\Area::AREA_ADMINHTML);

        parent::__construct();
    }

    /**
     * Initialization of the command
     *
     * @return void
     */
    protected function configure()
    {
        $this->setName('sr:customerattribute')
            ->setDescription('Add customer attribute');
        parent::configure();
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        ini_set('memory_limit', '-1');

        $this->output = $output;

        try {
            $output->writeln(
                "Start"
            );

            /** @var CustomerSetup $customerSetup */
            $customerSetup = $this->customerSetupFactory->create(['setup' => $this->setup]);

            // Add new customer attribute
            $customerSetup->addAttribute(
                Customer::ENTITY,
                'company',
                [

                    'label'                 => 'Company',
                    'input'                 => 'text',
                    'required'              => false,
                    'sort_order'            => 1000,
                    'position'              => 1000,
                    'visible'               => true,
                    'system'                => false,
                    'is_used_in_grid'       => true,
                    'is_visible_in_grid'    => false,
                    'is_filterable_in_grid' => false,
                    'is_searchable_in_grid' => false,
                    'default'               => '0'
                ]
            );

            // add attribute to form
            /** @var  $attribute */
            $attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'company');
            $attribute->setData('used_in_forms', ['adminhtml_customer', 'customer_account_create', 'customer_account_edit']);
            $attribute->save();

            $output->writeln(
                "<info>Completed</info>"
            );
        } catch (\Exception $e) {
            $output->writeln('<error>' . $e->getMessage() . '</error>');
            if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
                $output->writeln($e->getTraceAsString());
            }
            return;
        }
    }
}

Command


php bin/magento sr:customerattribute
1
  • Thank you for your answer. As a suggestion I would recommend not setting the area code in the constructor(or at least try catch it) as it might result in an Area code is already set error, if there are two cli commands that are setting the code in the constructor. As you might know Magento instantiates all cli commands at a certain point. thanks again. Feb 9, 2018 at 16:46

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.