Question

In my module I want to do some things if a product in the cart has a custom attribute 'servicepack'.

So by using the /etc/catalog_attributes.xml I exposed the property

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Catalog:etc/catalog_attributes.xsd">
    <group name="quote_item">
        <attribute name="servicepack"/>
    </group>
</config>

Next, I added my logic.

/** @var /Magento\Quote\Model\Quote $quote */
$quoteItems = $quote->getItems();
foreach($quoteItems as $cartItem){

    $product = $cartItem->getProduct(); //This is the configurable product
    $simpleId= $product->getIdBySku($product->getSku());

    /** @var ProductRepositoryInterface $this->productRepository */
    $simpleProduct = $this->productRepository->getById($simpleId); //Seems overkill?

    if($simpleProduct->getData('servicepack') == 123){ //This property is only on the simple product
        // do stuff
    }
}

I doubt this is the correct way to handle this situation.

The thing that confuses me:
The $cartItem is a configurable product. My 'servicepack' attribute is only set on the simple product. So I need to get the simple product data. I solved this by getting the simple product id, and fetching the simple product from the ProductRepository.

However, this seems inefficient, because it causes a db query for each product.

Question: Is it possible to get the simple product data without a database query?
For example: $product->getSimpleObject($product->getSku()); //Returns the $simpleProduct

Or would my solution be considered a decent way to handle things?

Was it helpful?

Solution

Question is a bit old but as I encountered the problem aswell now on Magento 2.3.5 I want to answer it.

It is easy but not obviously. You need to use $quote->getItemsCollection(); instead of $quote->getItems();. This will give you a collection object with the parent AND child products. If you only need to consider the simple products, then change your code like this:

/** @var /Magento\Quote\Model\Quote $quote */
$quoteItems = $quote->getItemsCollection();
foreach($quoteItems as $cartItem){

    if($cartItem->getProductType() !== 'simple') {
        continue;
    }
                        }
    if($cartItem->getData('servicepack') == 123){ //This property is only on the simple product
        // do stuff
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top