3

When adding an EAV attribute in an install script (Setup/InstallData.php or Setup/UpgradeData.php), the third argument to the addAttribute method is an array of information customizing the created attribute. An example (from this related question) is shown below:

$eavSetup->addAttribute(
    \Magento\Catalog\Model\Product::ENTITY,
    'some_attr',
    [
        'type' => '',
        'backend' => '',
        'frontend' => '',
        'label' => 'Test Attribute',
        'input' => '',
        'class' => '',
        'source' => '',
        'global' => \Magento\Catalog\Model\Resource\Eav\Attribute::SCOPE_GLOBAL,
        'visible' => true,
        'required' => false,
        'user_defined' => false,
        'default' => 0,
        'searchable' => false,
        'filterable' => false,
        'comparable' => false,
        'visible_on_front' => false,
        'used_in_product_listing' => true,
        'unique' => false,
        'apply_to' => ''
    ]
);

A lot of those array values are left blank, and many of them seem applicable only to certain entity types (e.g. the used_in_product_listing key probably wouldn't be added on a customer_address attribute).

Where can one find the range of possible keys for this array? Is it dependent on the attribute's entity type?

1 Answer 1

2

The addAttribute method in Magento\Eav\Setup\EavSetup.php passes the array through a PropertyMapperInterface:

public function addAttribute($entityTypeId, $code, array $attr)
    {
        $entityTypeId = $this->getEntityTypeId($entityTypeId);

        $data = array_replace(
            ['entity_type_id' => $entityTypeId, 'attribute_code' => $code],
            $this->attributeMapper->map($attr, $entityTypeId)
        );

github link

In the Eav module's di.xml, we find that the implementation preference for PropertyMapperInterface is Model\Entity\Setup\PropertyMapper\Composite.php. As the class name suggests, this class simply aggregates the functionality specified by PropertyMapperInterface implementations in other modules:

public function map(array $input, $entityTypeId)
{
    $data = [];
    foreach ($this->propertyMappers as $class) {
        if (!is_subclass_of($class, \Magento\Eav\Model\Entity\Setup\PropertyMapperInterface::class)) {
            throw new \InvalidArgumentException(
                'Property mapper ' .
                $class .
                ' must' .
                ' implement \Magento\Eav\Model\Entity\Setup\PropertyMapperInterface'
            );
        }
        $data = array_replace($data, $this->objectManager->get($class)->map($input, $entityTypeId));
    }
    return $data;
}

github link

These other implementations are injected into the Composite class's constructor, again, through dependency injection. For example, all EAV attributes receive treatment from Magento\Eav\Model\Entity\Setup\PropertyMapper.php, due to another entry in Eav's di.xml:

<type name="Magento\Eav\Model\Entity\Setup\PropertyMapper\Composite">
    <arguments>
        <argument name="propertyMappers" xsi:type="array">
            <item name="default" xsi:type="string">Magento\Eav\Model\Entity\Setup\PropertyMapper</item>
        </argument>
    </arguments>
</type>

github link

The implementation looks something like this:

public function map(array $input, $entityTypeId)
{
    return [
        'attribute_model' => $this->_getValue($input, 'attribute_model'),
        'backend_model' => $this->_getValue($input, 'backend'),
        'backend_type' => $this->_getValue($input, 'type', 'varchar'),
        ...
    ]
}

github link

Note how the keys specified in the array $attr of the original addAttribute method map to slightly different column names in the database.

What about used_in_product_listing? Sure enough, scouring through the relevant modules' di.xml files, one can find that Magento\Catalog appends a PropertyMapperInterface to the Composite, and in its implementation resides the line:

'used_in_product_listing' => $this->_getValue($input, 'used_in_product_listing', 0),

github link

Later on in the EavSetup class's addAttribute method, descending a bit into private internal method calls, one can find that some of these database columns reside not in the main eav_attribute table, but in an additional data table specified by the eav_entity_type table's additional_attribute_table column. In the case of used_in_product_listing, it is in fact a column in the catalog_eav_attribute table.

Determining the actual function of each of these array keys is an entirely different exercise. However, with this general method, developers can at least easily determine the scope of configuration options when programatically creating a new attribute.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.