I'm attempting to get a parent configurable product SKU from one of it's child simple products' SKU or ID. My understanding is that a simple can belong to multiple configurables, but I want the specific configurable the customer added to their cart. I read a related question but it gets all parent configurables.
I'm using Magento EE 1.12
EDIT: More detail on what I'm doing. When a customer checks out successfully I'm attempting to get SKU's of simples and the configurable the customer checked out with.
Attempting to apply code to:
app/design/frontend/enterprise/mytheme/template/checkout/success.phtml
If the configurable is in the cart already I think you can interrogate the cart to find the configurable and its simple ID.
$myTargetSimpleProductId = $someIdThatYouKnow;
$quote = Mage::getSingleton('checkout/session')->getQuote();
$cartItems = $quote->getAllVisibleItems();
foreach ($cartItems as $item){
if ($option = $item->getOptionByCode('simple_product')) {
$productIdArray[] = $option->getProduct()->getId(); //for the record
if ($option->getProduct()->getId()==$myTargetSimpleProductId ){
$myMatchingConfigurableProductId = $item->getProductId(); //capture the ID of the configurable
}
}
}
//$productIdArray holds a list of all the IDs of simple products that are in the basket due to configurables.
echo("The answer is ".$myMatchingConfigurableProductId);
Code adapted from this Q&A and that Q&A and not tested so let me know if this bombs horribly and you can't figure out all the corrections.
****EDIT to explain the code a bit more following the comment below ***
Overall, it helps to understand that when someone adds a configurable product to the cart Magento principally stores the product ID of the configurable not the product ID of the underlying simple product. But Magento being Magento the configured product in the cart is a complex object, part of which is a reference to the underlying simple product.
So:
$item->getProductId(); //Really means [pseudo code] $item->getConfiguredProductId()
$item->getOptionByCode('simple-product') //Accesses the underlying simple product object, hence
$item->getOptionByCode('simple-product')->getProduct()->getId() //gives accesse to the ID of the underlying simple product - ie the thing you want to test.
Now, if you are on the success page the challenge is how to access the order items. There are a sprinkling of answers on Stack Overflow for that and here is a sampling:
$_order = Mage::getModel('sales/order')->loadByIncrementId($this->getOrderId());
foreach ($_order->getAllItems() as $item) {
due to this Q&A. Or
$_customerId = Mage::getSingleton('customer/session')->getCustomerId();
$lastOrderId = Mage::getSingleton('checkout/session')->getLastOrderId();
$order = Mage::getSingleton('sales/order');
$order->load($lastOrderId);
foreach ($order->getItemsCollection() as $item) {
or from an observer function:
$order = $observer->getOrder();
/* @var $item Mage_Sales_Model_Order_Item */
foreach ($order->getItemsCollection() as $item) {
But I think you might benefit most from this tutorial from the Magento savvy Yireo:
$orderId = Mage::getSingleton('checkout/session')->getLastRealOrderId();
$order = Mage::getModel('sales/order')->loadByIncrementId($orderId);
$cartItems = $order->getAllItems();
foreach($cartItems as $item) {
due to Jisse Reitsma of Yireo.com
So you should be all set. There are a few bits and pieces to string together into your final code but I think you are either putting your code in template/checkout/success.phtml
or in an observer on checkout_type_onepage_save_order_after
and the snippets above will guide you.
****FURTHER EDITS***
If you have a $product
that is product_type = 'configurable'
then to get its SKU you should call $product->getData('sku');
if you only call $product->getSku();
that will always return the simple SKU due to
//file: app/code/core/Mage/Core/Catalog/Model/Product.php
//class: Mage_Catalog_Model_Product
public function getSku()
{
return $this->getTypeInstance(true)->getSku($this);
}
and if you follow the code, you find
//file: app/code/core/Mage/Core/Catalog/Model/Product/Type/Configurable.php
//class: Mage_Catalog_Model_Product_Type_Configurable
public function getSku($product = null)
{
$sku = $this->getProduct($product)->getData('sku');
if ($this->getProduct($product)->getCustomOption('option_ids')) {
$sku = $this->getOptionSku($product,$sku);
}
return $sku;
}
I would add that I have been running lots of code tests. When I set up an observer on the event checkout_type_onepage_save_order_after
then
$cartItems = $observer->getEvent()->getOrder()->getAllVisibileItems();
foreach ($cartItems as $item){
if ($item->getProductType() == 'configurable') {
$skuConfigurable = $item->getProduct()->getData('sku');
$skuMatchingSimple = $item->getProduct()->getSku();
Mage::log("skuConfigurable ".$skuConfigurable." has skuMatchingSimple ".$skuMatchingSimple, null, 'mylogfile.log');
}else{
Mage::log("Configurable SKU"." (not configurable product)", null, 'mylogfile.log');
}
}
Works a treat, but when I access the order items from within success.phtml
then both getSku()
and getData('sku')
both return the SKU of the configurable. Which leads me to think that I am not loading the sales/order
correctly or not understanding how to ascertain the 'configurable option' from the configurable $item
. But I can't figure out why there is that difference between `$item' in the observer compared to the success.phtml.
You probably know this already but I thought I would add: If you catch the event then you can access both the sale/quote and the sale/order objects but by the time you get to success.phtml the sales/quote object has been reset and you can only access sale/order (which I think is okay for you if all you need is the configurable sku).
Here is the code I am running in success.phtml, for me it only returns the config SKU
<?php //TEST CODE to retrieve SKUs from the order
$_checkoutSession = Mage::getSingleton('checkout/session');
$_customerSession = Mage::getSingleton('customer/session');
$orderId = Mage::getSingleton('checkout/session')->getLastRealOrderId();
$order = Mage::getModel('sales/order')->loadByIncrementId($orderId);
echo("<br>Order Id".$orderId);
$myTargetSimpleProductId = 42;//$someIdThatYouKnow;
//$cartItems = $order->getAllVisibleItems(); //returns the configurable items only
$cartItems = $order->getAllItems();
Mage::log(':PHTML--PHTML--PHTML--PHTML--PHTML--PHTML--PHTML--PHTML--', null, 'mylogfile.log');
Mage::log(':', null, 'mylogfile.log');
Mage::log('cartItems (from order):', null, 'mylogfile.log');
foreach ($cartItems as $item){
Mage::log("product_id".$item->getProductId(), null, 'mylogfile.log');
Mage::log("product_type".$item->getProductType(), null, 'mylogfile.log');
Mage::log("product_real_type".$item->getRealProductType(), null, 'mylogfile.log');
if ($option = $item->getOptionByCode('simple_product')) { //NEVER RETURNS TRUE, why?
Mage::log("item_opByCode_getProd_getId".$item->getOptionByCode('simple_product')->getProduct()->getId(), null, 'mylogfile.log');
}else{
Mage::log("item_opByCode_getProd_getId"." (not simple_product option)", null, 'mylogfile.log');
}
if ($item->getProductType() == 'configurable') {
$dummy = $item->getProduct()->getData('sku');
Mage::log("Configurable SKU ".$dummy, null, 'mylogfile.log'); $myAnswers[]=array('simpleSku'=>$item->getProduct()->getSku(),'configurableSku'=>$item->getProduct()->getData('sku')); //in success.phtml these two are always the same (the configurable SKU)
}else{
Mage::log("Configurable SKU"." (not configurable product)", null, 'mylogfile.log');
}
Mage::log("item options".print_r($item->getOptions(),true), null, 'mylogfile.log');
Mage::log("getProduct()->getId()".$item->getProduct()->getId(), null, 'mylogfile.log');
Mage::log("getProduct()->getSku".$item->getProduct()->getSku(), null, 'mylogfile.log');
Mage::log("getProduct()->getName()".$item->getProduct()->getName(), null, 'mylogfile.log');
Mage::log("SKUs : ".print_r($myAnswers,true), null, 'mylogfile.log');
Mage::log("<br>********************************", null, 'mylogfile.log');
if($item->getOptions()){ //NEVER RUNS - how get the configurable product options?
echo("OPTIONS".print_r($item->getOptions(),true));
}
}
echo("SKU's array".print_r($myAnswers,true));
I hope something here works for you. One time in the past I wrote a theme that only puts the simple product in the cart even if it originated as a configurable option so maybe worth checking your theme isn't doing that (by developing this code in the default theme until it works)