Question

The only solution i found so far is to add cacheable="false" to recently_viewed block in xml, but this did not work. Is there any other way to force magento show "Recently Viewed" block on product page when Full Page Cache is enable?

Was it helpful?

Solution 2

I finally made it work. So the reason the block not show up is because session in magento act a bit odd when Full Page Cache is enable. And that's why in sql query that gets recently viewed products we have empty visitor_id or customer_id and as a result - 0 records found. To solve this I used \Magento\Framework\App\Http\Context object and saved visitor_id or customer_id in there.

Here is the complete solution:

in Vendor/Module/di.xml

<preference for="Magento\Reports\Model\ResourceModel\Product\Index\Viewed\Collection" 
    type="Vendor\Module\Model\ResourceModel\Product\Index\Viewed\Collection"/>

In Vendor\Module\Model\ResourceModel\Product\Index\Viewed\Collection

namespace Vendor\Module\Model\ResourceModel\Product\Index\Viewed;

class Collection extends \Magento\Reports\Model\ResourceModel\Product\Index\Viewed\Collection
{

    protected $httpContext;

    public function __construct(
        \Magento\Framework\Data\Collection\EntityFactory $entityFactory,
        \Psr\Log\LoggerInterface $logger,
        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Eav\Model\Config $eavConfig,
        \Magento\Framework\App\ResourceConnection $resource,
        \Magento\Eav\Model\EntityFactory $eavEntityFactory,
        \Magento\Catalog\Model\ResourceModel\Helper $resourceHelper,
        \Magento\Framework\Validator\UniversalFactory $universalFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Module\Manager $moduleManager,
        \Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory,
        \Magento\Catalog\Model\ResourceModel\Url $catalogUrl,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Framework\Stdlib\DateTime $dateTime,
        \Magento\Customer\Api\GroupManagementInterface $groupManagement,
        \Magento\Customer\Model\Visitor $customerVisitor,
        \Magento\Framework\App\Http\Context  $httpContext,
        \Magento\Framework\DB\Adapter\AdapterInterface $connection = null
    ) {

        parent::__construct(
            $entityFactory,
            $logger,
            $fetchStrategy,
            $eventManager,
            $eavConfig,
            $resource,
            $eavEntityFactory,
            $resourceHelper,
            $universalFactory,
            $storeManager,
            $moduleManager,
            $catalogProductFlatState,
            $scopeConfig,
            $productOptionFactory,
            $catalogUrl,
            $localeDate,
            $customerSession,
            $dateTime,
            $groupManagement,
            $customerVisitor,
            $connection
        );

        $this->httpContext= $httpContext;
    }

    protected function _getWhereCondition()
    {
      $condition = [];
      $myCustomerId = $this->httpContext->getValue('my_customer_id');
      $myVisitorId = $this->httpContext->getValue('my_visitor_id');

      if($myCustomerId){
          $condition['customer_id'] = $myCustomerId;
      }elseif ($this->_customerSession->isLoggedIn()) {
          $condition['customer_id'] =    $this->_customerSession->getCustomerId();
          $this->httpContext->setValue('my_customer_id',$condition['customer_id'],false);
      }elseif ($this->_customerId) {
        $condition['customer_id'] = $this->_customerId;
        $this->httpContext->setValue('my_customer_id',$condition['customer_id'],false);
      }elseif($myVisitorId) {
         $condition['visitor_id'] = $myVisitorId;
      }else{
         $condition['visitor_id'] = $this->_customerVisitor->getId();
         if($condition['visitor_id'])
           $this->httpContext->setValue('my_visitor_id',$condition['visitor_id'],false);
        }

      return $condition;
   }
}

OTHER TIPS

This is a known issue with Magento 2, the issue can be tracked on GitHub here.

I believe the block will need 'hole punching' through the cache, there are some answers on how to disable the cache per block here and here There is also some related info on the dev docs here.

Be careful using cacheable="false" as it will prevent the whole page from being cached (this may be changed in a future update, if so please update this answer and remove this paragraph).

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top