3

General Context

When adding custom attributes to EAV-storage data types such as customers and customer_addresses, two seemingly redundant configuration values are allowed to be passed in:

// File: InstallData.php

public function install(...) {
    /** @var Magento\Eav\Setup\EavSetup */
    $eavSetup = $this->eavSetupFactory->create(...);

    $eavSetup->addAttribute(
        Magento\Customer\Model\Indexer\Address\AttributeProvider::ENTITY,
        'my_custom_attr',
        [
            'system'       => true,
            'user_defined' => false
        ]
    );
}

Other questions have addressed the question of what exactly a user_defined custom attribute means: the attribute is considered a "system" attribute (note the ambiguous terminology here), and as such it will not appear on the admin as removable because it is considered essential to the operation of Magento.

Specific Context

However, when omitting the system and user_defined configuration values altogether, I found that the attributes I defined defaulted to 'system' => true and 'user_defined' => false. This behavior seems to be due to the following two lines of code in PropertyMapper.php files:

// File: Magento/Customer/Model/ResourceModel/Setup/PropertyMapper.php
// Line: 27
'is_system' => $this->_getValue($input, 'system', 1),

// ...

// File: Magento/Eav/Model/Entity/Setup/PropertyMapper.php
// Line: 35
'is_user_defined' => $this->_getValue($input, 'user_defined', 0),

Based on the location of the two aforementioned files, I would predict that is_system relates specifically to customer attributes, and is_user_defined relates to attributes of any entity type.

When I later attempted to set and save those attributes via a repository, as such:

/** @var \Magento\Customer\Api\Data\AddressInterface */
$address = $this->addressRepository->getById(...);
$address->setCustomAttribute('my_custom_attr', 'my_custom_value');
$this->addressRepository->save($address);

...I found that my custom attribute was not even exposed by the engine, due to the following lines of code:

// File: Magento/Customer/Model/Metadata/AddressMetadata.php
// Lines: 121-143
public function getCustomAttributesMetadata($dataObjectClassName = AddressMetadataInterface::DATA_INTERFACE_NAME)
{
    ...
    foreach ($this->getAllAttributesMetadata() as $attributeMetadata) {
        ...
        if (!$isDataObjectMethod && !$attributeMetadata->isSystem()) {
            $customAttributes[] = $attributeMetadata;
        }
    }
}

(The link to the Magento source is here.)

I had to set 'system' => false in my InstallData.php script in order for the custom attribute to be accessible via the program, yet I left user_defined untouched.

Question

What is the difference between these two configuration values from a human perspective? How do they affect each other, if at all?

0

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.