1

I need to exclude a breadcrumbs block from cache on product page.

But I can't use cacheable="false" construction because the whole page will be excluded from cache.

Also I can't use _isScopePrivate because it's deprecated.

I'm looking at this article on magento docs and trying to create getIdentities method in the breadcrumbs block but still that block always in the cache anyway. Magento version - 2.2.2 I'm using varnish cache, don't know if approach is different from FPC in this case.

Can someone help?

0

I am having the same issue.

The problem is that full page cache using varnish for example caches the page based on a unique url.

If for example you have category paths disabled for product urls, the cache has no way of knowing the different versions of breadcrumbs used if that product is visible in more than 1 categories.

What actually solves the issue is writing a plugin which loads the breadcrumbs using ajax and sets the category last viewed.

The following steps need to be followed

  1. On category page you save the current category by making a call to a custom controller with the category_id as data using ajax. here you save the last viewed category_id in the catalog_session

Code SetCategoryViewed Controller (extends \Magento\Framework\App\Action\Action):

public function __construct(
    \Magento\Framework\App\Action\Context $context,
    \Magento\Framework\Registry $coreRegistry,
    \Magento\Catalog\Model\Session $catalogSession
) {
    $this->_catalogSession = $catalogSession;
    $this->_coreRegistry = $coreRegistry;
    parent::__construct($context);
}

public function execute(){
    $category_id = (int) $this->getRequest()->getParam('category_id');
    if($category_id){               
         $this->_catalogSession->setLastVisitedCategoryId($category_id);
         $this->_catalogSession->setLastViewedCategoryId($category_id);
    }
     $this->getResponse()->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0', true);
     return;
}
  1. On the product page you make a call to custom controller where you return the html of the breadcrumbs. Here you retrieve the lastViewedCategoryId from the catalog_session also send the product id to this controller.

Code getBreadcrumbsProduct Controller (extends \Magento\Catalog\Controller\Product\View):

public function __construct(
    \Magento\Framework\App\Action\Context $context, 
    \Magento\Catalog\Helper\Product\View $viewHelper, 
    \Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory, 
    \Magento\Framework\View\Result\PageFactory $resultPageFactory, 
    \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory, 
    \Magento\Framework\View\LayoutFactory $layoutFactory,   
    \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, 
    \Magento\UrlRewrite\Model\UrlFinderInterface $urlFinder, 
    \Magento\Catalog\Model\Product $productModel, 
    \Magento\Store\Model\StoreManagerInterface $storeManager, 
    \Magento\Framework\Registry $coreRegistry,
    \Magento\Catalog\Model\Session $catalogSession
) {
    $this->layoutFactory = $layoutFactory;

    $this->_catalogSession = $catalogSession;

    parent::__construct( 
        $context, 
        $viewHelper, 
        $resultForwardFactory, 
        $resultPageFactory, 
        $resultLayoutFactory, 
        $resultJsonFactory, 
        $urlFinder, 
        $productModel, 
        $storeManager, 
        $coreRegistry 
    ); 
}

public function execute(){
    $productId = (int) $this->getRequest()->getParam('id');
    $categoryId = (int) $this->_catalogSession->getLastVisitedCategoryId();

    $page = $this->resultPageFactory->create(false, ['isIsolated' => true]);    
    if(!$product = $this->_initProduct()){ 
    if($categoryId){
        $params = new \Magento\Framework\DataObject();
        $params->setCategoryId($categoryId);
        $this->viewHelper->prepareAndRender($page, $productId, $this,$params);
    }else{
        $this->viewHelper->prepareAndRender($page, $productId, $this);
    }
}
    $layout = $this->layoutFactory->create();
    $layout_a = $layout->createBlock('Magento\Theme\Block\Html\Breadcrumbs','breadcrumbs');
    $layout_b = $layout->createBlock('Gc\Category\Block\ExtendBreadcrumbs'); 

    $this->getResponse()->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0', true);

$this->getResponse()->setBody($layout_a->toHtml());

return;
}
  1. After that you create the corresponding ajax scripts and replace the breadcrumbs block in the layout of catalog_product_view.xml. Make a new breadcrumb template and replace HTML with the response of the ajax call.

Hope this helps.

P.s. i know this is not best practice by any means but it gets the job done.

0

Try it like this then:

 <referenceContainer name="content">
    <referenceBlock name="breadcrumbs">
        <arguments>
            <argument name="cacheable" xsi:type="boolean">false</argument>
        </argument>
    </referenceBlock>
</referenceContainer>

Edit: Adding cacheable: false to a block, will result the whole page won't be caching.

  • 1
    NO! DON'T USE THIS CODE! with cacheable=false whole page is not cached! – LucScu Sep 3 '18 at 13:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.