Magento pass current product ID to module

2019-01-22 10:23发布

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?

2条回答
家丑人穷心不美
2楼-- · 2019-01-22 10:47

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();
}
查看更多
手持菜刀,她持情操
3楼-- · 2019-01-22 10:48

you should have in the controller of your module something which init the registration of the current product. You will need to post between the page visited by a user the id of your product (recommended) or save it in a session. Here is an example of what you can do in a controller:

protected function _initAction(){

    if(! Mage::registry('current_product')){
        Mage::register('current_product', Mage::getModel('catalog/product'));
    }

    $id = $this->getRequest()->getParam('id');
    if (!is_null($id)) {
        $model = Mage::registry('current_product')->load($id);

        if (! $model->getId()) {
            $this->_getSession()->addError(Mage::helper('catalog')->__('This product item no longer exists'));
            $this->_redirect('*/*/');
            return;
        }
    }

    return $this;
}

public function indexAction()
{
  $this->_initAction();
  // your code below
}
查看更多
登录 后发表回答