1

Hello everyone i would like to add an extension_attribute to quote item in magento 2. I create extension attribute:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Quote\Api\Data\CartItemInterface">
        <attribute code="image" type="string" />
    </extension_attributes>
</config>

Then i have created plugin that set an extension attribute "image" to every quote item in qoute, this plugin is running on afterGet magento rest endpoint

"V1/guest-carts/:cartId/totals":

/**
 * @var CartItemExtensionFactory
 */
protected $cartItemExtension;

/**
 * @param CartItemExtensionFactory $cartItemExtension
 * @param ProductRepositoryInterfaceFactory $productRepository
 */
public function __construct(
    CartItemExtensionFactory $cartItemExtension
) {
    $this->cartItemExtension = $cartItemExtension;
}

/**
 * Add attribute values
 *
 * @param CartRepositoryInterface $subject ,
 * @param   $quote
 * @return mixed $quoteData
 * @throws NoSuchEntityException
 */
public function afterGet(
    CartRepositoryInterface $subject,
    $quote
) {
    return $this->setAttributeValue($quote);
}

/**
 * set value of attributes
 *
 * @param $quote
 * @return mixed $extensionAttributes
 * @throws NoSuchEntityException
 */
private function setAttributeValue($quote)
{
    if ($quote->getItemsCount()) {
        foreach ($quote->getItems() as $item) {
            $extensionAttributes = $item->getExtensionAttributes();
            if ($extensionAttributes === null) {
                $extensionAttributes = $this->cartItemExtension->create();
            }
            $extensionAttributes->setImage('fooo');
            $item->setExtensionAttributes($extensionAttributes);
        }
    }

    return $quote;
}

But in response there is no extension_attributes in quote item. When i debug it in PHPSTORM i see that attribute is set in _data object but it is not returning in response.

My response in postman:

{
    "grand_total": 882.91,
    "base_grand_total": 1085.98,
    "subtotal": 882.91,
    "base_subtotal": 882.91,
    "discount_amount": 0,
    "base_discount_amount": 0,
    "subtotal_with_discount": 882.91,
    "base_subtotal_with_discount": 882.91,
    "shipping_amount": 0,
    "base_shipping_amount": 0,
    "shipping_discount_amount": 0,
    "base_shipping_discount_amount": 0,
    "tax_amount": 203.07,
    "base_tax_amount": 203.07,
    "weee_tax_applied_amount": null,
    "shipping_tax_amount": 0,
    "base_shipping_tax_amount": 0,
    "subtotal_incl_tax": 1085.98,
    "shipping_incl_tax": 0,
    "base_shipping_incl_tax": 0,
    "base_currency_code": "PLN",
    "quote_currency_code": "PLN",
    "items_qty": 2,
    "items": [
        {
            "item_id": 1324,
            "price": 21.13,
            "base_price": 21.13,
            "qty": 1,
            "row_total": 21.13,
            "base_row_total": 21.13,
            "row_total_with_discount": 0,
            "tax_amount": 4.86,
            "base_tax_amount": 4.86,
            "tax_percent": 23,
            "discount_amount": 0,
            "base_discount_amount": 0,
            "discount_percent": 0,
            "price_incl_tax": 25.99,
            "base_price_incl_tax": 25.99,
            "row_total_incl_tax": 25.99,
            "base_row_total_incl_tax": 25.99,
            "options": "[{\"value\":\"+30GB\",\"label\":\"Transfer Size\"}]",
            "weee_tax_applied_amount": null,
            "weee_tax_applied": null,
            "name": "Transfer"
        },
        {
            "item_id": 1325,
            "price": 861.78,
            "base_price": 861.78,
            "qty": 1,
            "row_total": 861.78,
            "base_row_total": 861.78,
            "row_total_with_discount": 0,
            "tax_amount": 198.21,
            "base_tax_amount": 198.21,
            "tax_percent": 23,
            "discount_amount": 0,
            "base_discount_amount": 0,
            "discount_percent": 0,
            "price_incl_tax": 1059.99,
            "base_price_incl_tax": 1059.99,
            "row_total_incl_tax": 1059.99,
            "base_row_total_incl_tax": 1059.99,
            "options": "[{\"value\":\"Unlimited\",\"label\":\"Variant\"}]",
            "weee_tax_applied_amount": null,
            "weee_tax_applied": null,
            "name": "foo"
        }
    ],
    "total_segments": [
        {
            "code": "subtotal",
            "title": "sum",
            "value": 1085.98
        },
        {
            "code": "shipping",
            "title": "shipping",
            "value": 0
        },
        {
            "code": "tax",
            "title": "Tax",
            "value": 203.07,
            "extension_attributes": {
                "tax_grandtotal_details": [
                    {
                        "amount": 203.07,
                        "rates": [
                            {
                                "percent": "23",
                                "title": "Poland (standard)"
                            }
                        ],
                        "group_id": 1
                    }
                ]
            }
        },
        {
            "code": "grand_total",
            "title": "Sub",
            "value": 1085.98,
            "area": "footer"
        }
    ]
}

Can anyone tell me why there is no my extension_attribute image in every single quote item ?

| improve this question | | | | |
0

Not sure, but the first thing I noticed in your code is that you write plugin for \Magento\Quote\Api\CartRepositoryInterface but should be for \Magento\Quote\Api\GuestCartTotalRepositoryInterface

Upd #1: The following works for me:

extension_attributes.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Quote\Api\Data\TotalsItemInterface">
        <attribute code="some_super_cool_attribute" type="string" />
    </extension_attributes>
</config>

module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Underser_CartExtensionAttributes" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Quote"/>
        </sequence>
    </module>
</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\GuestCartTotalRepositoryInterface">
        <plugin name="underser_add_extension_attributes" type="Underser\CartExtensionAttributes\Plugin\Quote\TotalsPlugin"/>
    </type>
</config>

\Underser\CartExtensionAttributes\Plugin\Quote\TotalsPlugin

<?php

namespace Underser\CartExtensionAttributes\Plugin\Quote;

use Magento\Quote\Api\Data\TotalsInterface;
use Magento\Quote\Api\GuestCartTotalRepositoryInterface;
use Magento\Quote\Api\Data\TotalsItemInterface;
use Magento\Quote\Api\Data\TotalsItemExtensionInterfaceFactory;

class TotalsPlugin
{
    /**
     * @var TotalsItemExtensionInterfaceFactory
     */
    protected $totalsItemExtensionInterfaceFactory;

    /**
     * TotalsPlugin constructor.
     *
     * @param TotalsItemExtensionInterfaceFactory $totalsItemExtensionInterfaceFactory
     */
    public function __construct(TotalsItemExtensionInterfaceFactory $totalsItemExtensionInterfaceFactory)
    {
        $this->totalsItemExtensionInterfaceFactory = $totalsItemExtensionInterfaceFactory;
    }

    /**
     * After get items.
     *
     * @param GuestCartTotalRepositoryInterface $subject
     * @param TotalsInterface $result
     * @return TotalsInterface
     */
    public function afterGet(
        GuestCartTotalRepositoryInterface $subject,
        TotalsInterface $result
    ) {
        /** @var TotalsItemInterface $item */
        foreach ($result->getItems() as $item) {
            $extensionAttributes = $item->getExtensionAttributes();

            if (!$extensionAttributes) {
                $extensionAttributes = $this->totalsItemExtensionInterfaceFactory->create();
            }

            $extensionAttributes->setSomeSuperCoolAttribute('someSuperCoolAttributeValue');

            $item->setExtensionAttributes($extensionAttributes);
        }

        return $result;
    }
}
| improve this answer | | | | |
  • After applying your suggestion i'm getting the following error: Uncaught TypeError: Argument 1 passed to MyModuleName\QuoteCustomization\Plugin\QuotePlugin: :afterGet() must be an instance of Magento\Quote\Api\GuestCartTotalRepositoryInterface, instance of Magento\Quote\Model\QuoteRepository\Interceptor given, called in /Users/papryk/Sites/htdocs/magento-shop/vendor/magento/framework/Interception/Interceptor.php on line 146 and defined in /Users/papryk/Sites/htdocs/magento-shop/app/code/MyModuleName/QuoteCustomization/Plugin/QuotePlugin.php: 33 – Patryk Oct 11 '19 at 6:32
  • you need to change your plugin signature $subject should be \Magento\Quote\Api\GuestCartTotalRepositoryInterface – underser Oct 11 '19 at 12:44
  • @Patryk, please see the updated answer. Feel free to ping me, if you still face problems. – underser Oct 11 '19 at 15:39
  • Thank you very much, it's working now properly. I'm very grateful for your help. – Patryk Oct 14 '19 at 11:57

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.