0

I am trying to add a custom attribute to a quote item via the API, however I am struggling to see how Magento's architecture actually allows for this?

I have created the following files:

extension_attributes.xml:

<config>
    <extension_attributes for="Magento\Quote\Api\Data\CartItemInterface">
        <attribute code="my_custom_field" type="string">
            <resources>
                <resource  ref="anonymous"/>
            </resources>
        </attribute>
    </extension_attributes>
</config>

di.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Quote\Api\GuestCartItemRepositoryInterface">
        <plugin name="example" type="Brideo\Example\Model\GuestCart\GuestCartItemRepository\Plugin" sortOrder="100" disabled="false" />
    </type>
</config>

Brideo\Example\Model\GuestCart\GuestCartItemRepository\Plugin:

/**
     * @param GuestCartItemRepositoryInterface $subject
     * @param CartItemInterface                $entity
     *
     * @return CartItemInterface[]
     */
    public function beforeSave(
        GuestCartItemRepositoryInterface $subject,
        CartItemInterface $entity
    )
    {
            $extensionAttributes = $entity->getExtensionAttributes();

        if ($entity->getData('my_custom_field') || $extensionAttributes == null || $extensionAttributes->getMyCustomField() == null) {
            return [$entity];
        }

        $someEntity = $this->someRepo->get($extensionAttributes->getMyCustomField());

        $extensionAttributes->setMyCustomField($someEntity->getMyCustomField());
        $entity->setExtensionAttributes($extensionAttributes);

        return [$entity];
    }

I can see the extension attribute being added, however when Magento passes the cart item to the CartItemPersister::save() method it runs this code:

$item = $quote->addProduct(
                    $product,
                    $this->cartItemOptionProcessor->getBuyRequest($productType, $item)
                );

This code gives you the opportunity to add to the buy request but not add any custom data and it simply removes the extension attributes.

Any ideas? I think I might just have to create an additional mapping table even though it's not a many to many relationship.

1

So in the end I had to use the around method.

  • beforeSave I have no entity to save against
  • afterSave I have no data to save
  • aroundSave grab the data then save against the new entity

    public function aroundSave
    (
        \Magento\Quote\Api\GuestCartItemRepositoryInterface $subject,
        \Closure $proceed,
        \Magento\Quote\Api\Data\CartItemInterface $entity
    ) 
    {
        $extensionAttributes = $entity->getExtensionAttributes();
    
        if ($extensionAttributes == null || $extensionAttributes->getMyCustomField() == null) 
        {
            return [$entity];
        }
    
        /** @var \Magento\Quote\Api\Data\CartItemInterface|\Magento\Framework\Model\AbstractModel $cartItem */
        $cartItem = $proceed($entity);
        if (!$cartItem) 
        {
            return $cartItem;
        }
    
        $someData = $this->someRepo->get($extensionAttributes->getMyCustomField());
        $cartItem->setData('my_custom_id', $someData->getId());
        $this->itemResource->save($cartItem);
    
        return $cartItem;
    }
    
  • If someone could edit my answer and fix the formatting, that would be great. – Brideo May 10 '17 at 5:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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