Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.
This repository was archived by the owner on Nov 19, 2024. It is now read-only.

beforeSave functionality is incorrectly described #7786

Closed
@infinityredux

Description

@infinityredux

General issue

https://devdocs.magento.com/guides/v2.4/extension-dev-guide/extension_attributes/adding-attributes.html

Directly following the general patterns described on this page - for an extension attribute on a product, with a plugin connected to the product repository - the afterSave function will not update the extension attribute. For example, making an API call with updated extension attribute will leave it unchanged.

Description:

Essentially, the data in the product instance returned as the result of a save call (passed as the 2nd parameter to an 'after' plugin function) is not what was sent via the API.

After a little digging, the data that reaches the beforeSave function is correct. However, the final step in the product repository save process is a get call, presumably to refresh data, which correspondingly triggers the afterGet function to (re-)populate the extension attributes on the product returned as the result.

The code example on the page is using the ProductInterface that is the result returned from the function, due to the attribute sequence, hence why it can't / won't update the extension attribute.

However, it should also be noted that is specifically a peculiarity of the product repository and does not necessarily hold true for other repositories.

Possible solutions:

We can't simply return the original parameter object, because that would invalidate any processing carried out before / during save. Similarly, we can't just return the result object by itself, since that has the incorrect extension attributes and potentially might be used by something else. And we can't change this to a beforeSave function, because that causes potential issues with product creation (hard to link an extension attribute to a product that doesn't exist in the database yet.)

To resolve this correctly, you actually need both the result object and the original parameter object:

public function afterSave
(
     \Magento\Catalog\Api\ProductRepositoryInterface $subject,
     \Magento\Catalog\Api\Data\ProductInterface $result, /** result from the save call **/
     \Magento\Catalog\Api\Data\ProductInterface $entity  /** original parameter to the call **/
     /** other parameter not required **/
) {
    $extensionAttributes = $entity->getExtensionAttributes(); /** get original extension attributes from entity **/
    $ourCustomData = $extensionAttributes->getOurCustomData();
    $this->customDataRepository->save($ourCustomData);

    $resultAttributes = $result->getExtentionAttributes(); /** get extension attributes as they exist after save **/
    $resultAttributes->setOurCustomData($ourCustomData); /** update the extension attributes with correct data **/
    $result->setExtensionAttributes($resultAttributes);

    return $result;
}
...

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions