Browsed by
Tag: EAV

Use EavSetup to Import Attributes

Use EavSetup to Import Attributes

I recently had the issue that I needed to use the \Magento\Eav\Setup\EavSetup outside the setup-context.
To be a bit more concrete, I wanted to import attribute-sets, attributes and attribute-options without using an install-script.
My first idea was

in magento2 you can easily inject the ‘EavSetup’ via constructor injection and then use it in your own class

First try

So I injected into my class which worked out well in the development-mode.

But using the same code with the production-mode a fatal error occurred with a message like

After a short research and some debugging, it turned out that the “production”-mode was not the issue. The root of the problem was the output “setup:di:compile”-command created. And more over how the EavSetup is instantiated in general.

A brief digression

For better testing I wrote a short php-file which tries to instantiate my class with the help of the object-manager. It is based on the ‘index.php’ without the $bootstrap->run($app); line, instead of the run-method I call “getObjectManager” and work with the object-manager for my tests.

With these information I started my analysis how magento does it and how could I use the “EavSetup” for my purposes.
Here you can see some classes that are relevant in instantiating an EavSetup:

  • \Magento\Setup\Model\ObjectManagerProvider
  • \Magento\Setup\Module\DataSetupFactory
  • \Zend\ServiceManager\ServiceManager
  • \Magento\Framework\ObjectManager\Factory\Compiled::create
  • \Magento\Framework\ObjectManager\Config\Compiled::getArguments

The main issue was that \Magento\Framework\ObjectManager\Config\Compiled::getArguments  did not return the correct arguments.
So while I was not able to pass the arguments as needed, I had to figure out another way how to use the “EavSetup” in my class.

After debugging the magento instantiation of the “EavSetup”, I started to forge the magento process in my construct.

The Solution

The resulting solution looks something like this

Let me just explain in a few words what I had to do.

For a better understanding let us move from bottom to top, my goal was to create a “EavSetup” instance to reach this goal I had to use the EavFactorySetup->create()  method.
The EavSetupFactory has a dependency to the DataSetupFactory which itself needs a ObjectManagerProvider instance injected.
This is the interesting point in this manual dependency injection flow:
the ObjectManagerProvider now needs a ServiceManager to create the instance.  
That’s the main cause of our issue with di:compile and production mode. This dependency cannot be injected by the default ObjectManager and thus the above mentioned error occured.

So after manually building the dependencies and creating the objects, we could work around this issue.

In case you haven’t seen how the “setup/index.php” “application” works you should have a closer look at that.

Magento Certified Developer Plus
Fixing issues after changing product attribute type from varchar to text

Fixing issues after changing product attribute type from varchar to text

In some cases there is a need to change the backend type of a catalog product attribute from varchar to text. The purpose of this change is to get more than 255 characters space for a string value.

In this article I will cover the situation when problems occur after changing the backend type of an attribute.

The Problem

If the backend type of an attribute is changed, e.g. via install/upgrade script, Magento does not automatically copy and clean up old values. The consequence of that is that there are rudiments in the EAV value tables which cause some side effects. One of the side effects I was facing is editing a product which had a value for the affected attribute before the backend type change (in admin area). No values are displayed and there is no possibility to set a new value.

So what to do if the change already happened and there is a mix between old value table rudiments and new value table entries?

The Solution

One possible solution to solve the issue are the following SQL Statements, here is an example for changing from varchar to text (you need to find out the id of the attribute from the eav_attribute table – here {attribute_id}):

1. Copy the “value” from varchar table to text table for the case an entry for a product entity exists in both tables, but only if the “value” in the text table is null:

 2. Copy entries which do not exist in text value table, but exist in the varchar table

3. Delete entries from the varchar table

Important note

Please verify the SQL, whether it is suitable for your purpose. Best practice is also to test it in a local / staging system and to back up the live database before applying the SQL on production. The solution is not perfect: I myself faced the issue, that the enterprise indexer cronjob took about 4h after applying the SQL, which blocked other cronjobs to be executed (about 50K products in DB). Possible way to avoid this is to separate “malways” (enterprise indexer) and “mdefault” cronjobs.

I hope this  can be helpful. Feel free to comment if you faced this issue too or if you have any additions or a better solution.

Magento Certified Developer Plus
Thoughts about custom attributes and the way to manage them!

Thoughts about custom attributes and the way to manage them!

To add or update an EAV attribute in Magento, it is necessary to add setup scripts to your code base. If you don’t handle your custom attributes in setup scripts, you are not able to install your project from scratch, which could cause a lot of problems. For example, it makes it harder to run unit- and integration tests.

So lets assume that we are working in a team with 4 developers and everybody has a different task. Each task needs a custom attribute in a different entity_type.

I want to share my thoughts and summarize an overview of how the 4 developers could implement their setup scripts. Also, I want to show the advantages and disadvantages of each method.

Read More Read More