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.