Magento getJsonConfig Not Working on Second Call – How to Fix

configurable-productproduct-attribute

In my wishlist I'm calling getJsonConfig on each product. The ['attributes'] is the only information that I'm using. For the first/top product in the wishlist there is no problem. But the second product returns everything except the ['attributes'] index is empty.

If I remove the first/top product and force the second to become the new first/top product ['attributes'] is populated.

An example of what the first/top product returns is as follows

object(stdClass)#881 (7) {
["attributes"] => object(stdClass)#889 (1) {
["155"] => object(stdClass)#890 (4) {
  ["id"] => string(3) "155"
  ["code"] => string(4) "size"
  ["label"] => string(4) "Size"
  ["options"] => array(4) {
    [0] => object(stdClass)#882 (5) {
      ["id"] => string(2) "29"
      ["label"] => string(2) "XS"
      ["price"] => string(1) "0"
      ["oldPrice"] => string(1) "0"
      ["products"] => array(1) {
        [0] => string(3) "714"
      }
    }
    [1] => object(stdClass)#883 (5) {
      ["id"] => string(1) "4"
      ["label"] => string(1) "M"
      ["price"] => string(1) "0"
      ["oldPrice"] => string(1) "0"
      ["products"] => array(1) {
        [0] => string(3) "716"
      }
    }
    [2] => object(stdClass)#884 (5) {
      ["id"] => string(1) "3"
      ["label"] => string(1) "L"
      ["price"] => string(1) "0"
      ["oldPrice"] => string(1) "0"
      ["products"] => array(1) {
        [0] => string(3) "717"
      }
    }
    [3] => object(stdClass)#885 (5) {
      ["id"] => string(1) "5"
      ["label"] => string(1) "S"
      ["price"] => string(1) "0"
      ["oldPrice"] => string(1) "0"
      ["products"] => array(1) {
        [0] => string(3) "718"
      }
    }
  }
}
}
["template"] => string(9) "$#{price}"
["basePrice"] => string(3) "858"
["oldPrice"] => string(3) "858"
["productId"] => string(3) "715"
["chooseText"] => string(19) "Choose an Option..."
["taxConfig"] => object(stdClass)#886 (6) {
["includeTax"] => bool(false)
["showIncludeTax"] => bool(false)
["showBothPrices"] => bool(false)
["defaultTax"] => int(0)
["currentTax"] => int(0)
["inclTaxTitle"] => string(9) "Incl. Tax"
}
}

And the second looks like

object(stdClass)#964 (7) {
["attributes"] => array(0) {
}
["template"] => string(9) "$#{price}"
["basePrice"] => string(6) "127.57"
["oldPrice"] => string(6) "127.57"
["productId"] => string(3) "659"
["chooseText"] => string(19) "Choose an Option..."
["taxConfig"] => object(stdClass)#778 (6) {
["includeTax"] => bool(false)
["showIncludeTax"] => bool(false)
["showBothPrices"] => bool(false)
["defaultTax"] => int(0)
["currentTax"] => int(0)
["inclTaxTitle"] => string(9) "Incl. Tax"
}
}

I call this from the template like this

<?php
if($_product && $_product->isConfigurable()){
    $checkoutLinksBlock = $this->getLayout()->getBlockSingleton('catalog/product_view_type_configurable')->setTemplate('wishlist/item/column/configurable.phtml')->setProduct($_product);
    echo '<div style="display:none;" class="config-options" id="'. $_product->getId() .'">' . $checkoutLinksBlock->renderView() . '</div>';

}

$checkoutLinksBlock->renderView() just contains a zend_debug::dump($this->getJsonConfig());

getJsonConfig() refers to this function in app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php

public function getJsonConfig()
{
    $attributes = array();
    $options    = array();
    $store      = $this->getCurrentStore();
    $taxHelper  = Mage::helper('tax');
    $currentProduct = $this->getProduct();

    $preconfiguredFlag = $currentProduct->hasPreconfiguredValues();
    if ($preconfiguredFlag) {
        $preconfiguredValues = $currentProduct->getPreconfiguredValues();
        $defaultValues       = array();
    }

    foreach ($this->getAllowProducts() as $product) {
        $productId  = $product->getId();

        foreach ($this->getAllowAttributes() as $attribute) {
            $productAttribute   = $attribute->getProductAttribute();
            $productAttributeId = $productAttribute->getId();
            $attributeValue     = $product->getData($productAttribute->getAttributeCode());
            if (!isset($options[$productAttributeId])) {
                $options[$productAttributeId] = array();
            }

            if (!isset($options[$productAttributeId][$attributeValue])) {
                $options[$productAttributeId][$attributeValue] = array();
            }
            $options[$productAttributeId][$attributeValue][] = $productId;
        }
    }

    $this->_resPrices = array(
        $this->_preparePrice($currentProduct->getFinalPrice())
    );

    foreach ($this->getAllowAttributes() as $attribute) {
        $productAttribute = $attribute->getProductAttribute();
        $attributeId = $productAttribute->getId();
        $info = array(
           'id'        => $productAttribute->getId(),
           'code'      => $productAttribute->getAttributeCode(),
           'label'     => $attribute->getLabel(),
           'options'   => array()
        );

        $optionPrices = array();
        $prices = $attribute->getPrices();
        if (is_array($prices)) {
            foreach ($prices as $value) {
                if(!$this->_validateAttributeValue($attributeId, $value, $options)) {
                    continue;
                }
                $currentProduct->setConfigurablePrice(
                    $this->_preparePrice($value['pricing_value'], $value['is_percent'])
                );
                $currentProduct->setParentId(true);
                Mage::dispatchEvent(
                    'catalog_product_type_configurable_price',
                    array('product' => $currentProduct)
                );
                $configurablePrice = $currentProduct->getConfigurablePrice();

                if (isset($options[$attributeId][$value['value_index']])) {
                    $productsIndex = $options[$attributeId][$value['value_index']];
                } else {
                    $productsIndex = array();
                }

                $info['options'][] = array(
                    'id'        => $value['value_index'],
                    'label'     => $value['label'],
                    'price'     => $configurablePrice,
                    'oldPrice'  => $this->_prepareOldPrice($value['pricing_value'], $value['is_percent']),
                    'products'  => $productsIndex,
                );
                $optionPrices[] = $configurablePrice;
            }
        }
        /**
         * Prepare formated values for options choose
         */
        foreach ($optionPrices as $optionPrice) {
            foreach ($optionPrices as $additional) {
                $this->_preparePrice(abs($additional-$optionPrice));
            }
        }
        if($this->_validateAttributeInfo($info)) {
           $attributes[$attributeId] = $info;
        }

        // Add attribute default value (if set)
        if ($preconfiguredFlag) {
            $configValue = $preconfiguredValues->getData('super_attribute/' . $attributeId);
            if ($configValue) {
                $defaultValues[$attributeId] = $configValue;
            }
        }
    }

    $taxCalculation = Mage::getSingleton('tax/calculation');
    if (!$taxCalculation->getCustomer() && Mage::registry('current_customer')) {
        $taxCalculation->setCustomer(Mage::registry('current_customer'));
    }

    $_request = $taxCalculation->getDefaultRateRequest();
    $_request->setProductClassId($currentProduct->getTaxClassId());
    $defaultTax = $taxCalculation->getRate($_request);

    $_request = $taxCalculation->getRateRequest();
    $_request->setProductClassId($currentProduct->getTaxClassId());
    $currentTax = $taxCalculation->getRate($_request);

    $taxConfig = array(
        'includeTax'        => $taxHelper->priceIncludesTax(),
        'showIncludeTax'    => $taxHelper->displayPriceIncludingTax(),
        'showBothPrices'    => $taxHelper->displayBothPrices(),
        'defaultTax'        => $defaultTax,
        'currentTax'        => $currentTax,
        'inclTaxTitle'      => Mage::helper('catalog')->__('Incl. Tax')
    );

    $config = array(
        'attributes'        => $attributes,
        'template'          => str_replace('%s', '#{price}', $store->getCurrentCurrency()->getOutputFormat()),
        'basePrice'         => $this->_registerJsPrice($this->_convertPrice($currentProduct->getFinalPrice())),
        'oldPrice'          => $this->_registerJsPrice($this->_convertPrice($currentProduct->getPrice())),
        'productId'         => $currentProduct->getId(),
        'chooseText'        => Mage::helper('catalog')->__('Choose an Option...'),
        'taxConfig'         => $taxConfig
    );

    if ($preconfiguredFlag && !empty($defaultValues)) {
        $config['defaultValues'] = $defaultValues;
    }

    $config = array_merge($config, $this->_getAdditionalConfig());

    return Mage::helper('core')->jsonEncode($config);
}

As you can see the product Id section is different on each and I've checked that it is the product I think it is. The second object will populate the ["attributes"] if I remove the first product from the wishlist.

So why is there an issue getting this configuration data for multiple products on a single page.

P.S. I've tried this with lots of products so it's not a once off issue. It is consistent whatever products are in the wishlist.

Best Answer

In your case the problem is that you use getBlockSingleton, which probabably cache the information about the first product. Try to use createBlock() method. This will create new instance of the block and should solve your problem.

Related Topic