Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magento pass current product ID to module

I have a custom module that displays data on my product pages. My module needs to get the current product id. I tried using:

Mage::registry('current_product');

This works on the first load but when I refresh, current_product no longer has data with full page caching on.

Any ideas?

like image 679
rlflow Avatar asked Nov 17 '11 20:11

rlflow


People also ask

How do I load product by product ID in Magento 2?

Magento 2 load product by store id To load product by store id ,first we pass instance of \Magento\Catalog\Model\ProductFactory and create its object $_productFactory. In above code we use setStoreId() to set the store id value and load the product id. Here we use value of store id=1 and product id=13.

How do I find a products URL?

You can be assigned Product URL to any page in store for a redirect to Product page. If you want to get Only Url Key value, You can access by $product->getUrlKey() method. You can product full URL by getProductUrl() method.


1 Answers

The catalog product action controller isn't dispatched, when the full page cache handles the request (which makes sense to keep things fast). So, the registry variables are never set. I assume you are generating the block dynamically on the otherwise fully cached page. My recommendation is to try to avoid expensive loads, since that would undermine the speed improvements by the full page cache. You really want to cache the block if at all possible, even if it's a separate cache entry for each customer and each product.

That said, here is how to do that:

In the container, implement the _getIdentifier() method:

protected function _getIdentifier()
{
    return $this->_getCookieValue(Enterprise_PageCache_Model_Cookie::COOKIE_CUSTOMER, '');
}

Also expand the _getCacheId() method to include the return value of the method _getIdentifier() and a new placeholder attribute: product_id

protected function _getCacheId()
{
    return 'HOMEPAGE_PRODUCTS' . md5($this->_placeholder->getAttribute('cache_id') . ',' . $this->_placeholder->getAttribute('product_id')) . '_' . $this->_getIdentifier();
}

Next, in the block class, extend the method getCacheKeyInfo(). All entries in the cache_key_info array with a string index are set on the placeholder as attributes. That is how we can pass the product id to the placeholder.

public function getCacheKeyInfo()
{
    $info = parent::getCacheKeyInfo();
    if (Mage::registry('current_product'))
    {
        $info['product_id'] = Mage::registry('current_product')->getId();
    }
    return $info;
}

Then enable the method _saveCache() by not overriding it in your container class and returning false. So now, because the container returns a valid id from _getCacheId(), and _saveCache() is inherited from the parent class, the the block can be cached, and applied to the content in an efficient manner in Enterprise_PageCache_Model_Container_Abstract::applyWithoutApp().

You can set the lifetime of the cache entry by having your container extend from Enterprise_PageCache_Model_Container_Customer instead of Enterprise_PageCache_Model_Container_Abstract.

If you still need to pass the product_id to the block (even though it's cached now), you can do so in the _renderBlock() method of your container:

protected function _renderBlock()
{
    $blockClass = $this->_placeholder->getAttribute('block');
    $template = $this->_placeholder->getAttribute('template');

    $block = new $blockClass;
    $block->setTemplate($template)
        ->setProductId($this->_placeholder->getAttribute('product_id'));
    return $block->toHtml();
}
like image 87
Vinai Avatar answered Sep 27 '22 20:09

Vinai