Magento – Why $item->getSku() and $item->getProduct()->getSku() Return Different Values?

collection;magento-enterpriseordersproduct

Edit: originally this question was just about sales/order objects but I've found an identical problem with sales/quote objects too, so I'm editing it to include that.

I also added a TL;DR at the bottom which might be clearer for some people.


I'm trying to get information on the items from an order/quote, but have found that using $item->getSku() is not very intuitive.

It always returns the child SKU, even if I'm running it inside a getAllVisibleItems() loop (as opposed to just getAllItems()).

The SKU it returns is different from $item->getProduct()->getSku().

When called inside getAllVisibleItems() I would expect $item->getSku() to return the parent product's SKU and not the child SKU (because the parent is the one which is visible).

Edit: I've discovered an even more problematic issue. When I loop on a sales/quote collection instead of sales/order, the $item->getProduct()->getSku() call doesn't even return the correct (parent) SKU. It still returns the child-level SKU which is wrong. In order to get the correct parent-level SKU, I have to actually fully load the product (see the second block of code below).

Why is this happening?

Here's my code:

For sales/order collections:

<?php

$order = Mage::getModel("sales/order")->loadByIncrementId("123456");

foreach($order->getAllVisibleItems() as $orderItem) {
    echo "Item SKU =>    " . $orderItem->getSku();
    echo "Product SKU => " . $orderItem->getProduct()->getSku();
}

foreach($order->getAllItems() as $orderItem) {
    echo "Item SKU =>    " . $orderItem->getSku();
    echo "Product SKU => " . $orderItem->getProduct()->getSku();
}

// Output

getAllVisibleItems:
Item SKU    => SHOE1-SIZE5 // Parent product - misleading item SKU
Product SKU => SHOE1

Item SKU    => SHOE2-SIZE4 // Parent product - misleading item SKU
Product SKU => SHOE2       

getAllItems:
Item SKU    => SHOE1-SIZE5 // Parent product - misleading item SKU
Product SKU => SHOE1       

Item SKU    => SHOE1-SIZE5 // Child product - correct item SKU
Product SKU => SHOE1-SIZE5

Item SKU    => SHOE2-SIZE4 // Parent product - misleading item SKU
Product SKU => SHOE2

Item SKU    => SHOE2-SIZE4 // Child product - correct item SKU
Product SKU => SHOE2-SIZE4

For sales/quote collections:

$quote = Mage::getModel("sales/quote")->load("98765");

foreach($quote->getAllVisibleItems() as $quoteItem) {
    echo "Item SKU                 => " . $quoteItem->getSku();
    echo "Product SKU              => " . $quoteItem->getProduct()->getSku();
    echo "Fully Loaded Product SKU => " . Mage::getModel("catalog/product")->load($quoteItem->getProduct()->getId())->getSku();
}

foreach($quote->getAllItems() as $quoteItem) {
    echo "Item SKU                 => " . $quoteItem->getSku();
    echo "Product SKU              => " . $quoteItem->getProduct()->getSku();
    echo "Fully Loaded Product SKU => " . Mage::getModel("catalog/product")->load($quoteItem->getProduct()->getId())->getSku();
}

// Output

getAllVisibleItems:
Item SKU                 => SHOE1-SIZE5 // The child SKU (wrong)
Product SKU              => SHOE1-SIZE5 // Different behaviour than sales/order object
Fully Loaded Product SKU => SHOE1       // The parent SKU (correct)

Item SKU                 => SHOE2-SIZE4 // The child SKU (wrong)
Product SKU              => SHOE2-SIZE4 // Different behaviour than sales/order object
Fully Loaded Product SKU => SHOE2       // The parent SKU (correct)

getAllItems:
Item SKU                 => SHOE1-SIZE5 // Parent product - misleading item SKU
Product SKU              => SHOE1-SIZE5 // Misleading
Fully Loaded Product SKU => SHOE2       // Correct

Item SKU                 => SHOE1-SIZE5 // Child product - correct item SKU
Product SKU              => SHOE1-SIZE5 // Correct
Fully Loaded Product SKU => SHOE1-SIZE5 // Correct

Item SKU                 => SHOE2-SIZE4 // Parent product - misleading item SKU
Product SKU              => SHOE2-SIZE4 // Misleading
Fully Loaded Product SKU => SHOE2       // Correct

Item SKU                 => SHOE2-SIZE4 // Child product - correct item SKU
Product SKU              => SHOE2-SIZE4 // Correct
Fully Loaded Product SKU => SHOE2-SIZE4 // Correct

TL;DR

The TL;DR of this post is: These two SKUs come out different. Why?

$cartItems = Mage::getSingleton('checkout/cart')->getQuote()->getAllVisibleItems();

foreach ($cartItems as $cartItem) {

    // These two SKUs are different. Why?
    echo $cartItem->getProduct()->getSku();
    echo Mage::getModel("catalog/product")->load($cartItem->getProduct()->getId())->getSku();

}

Best Answer

I think it's an intended behaviour (see https://github.com/OpenMage/magento-mirror/blob/magento-1.9/app/code/core/Mage/Catalog/Model/Product/Type/Configurable.php#L832), possibly for display purposes, but I agree with you: for fashion products this is mostly the wrong expected behaviour.

It is very easy to get around that, though: just call

 $item->getProduct()->getData('sku')

instead of $item->getProduct()->getSku(). You should definitely avoid to reload the product during cart and order operations, since it's not needed and it might lead to performance issues.

Related Topic