How to get customer id from block when full page cache enable in magento 2

Today I discuss about getting customer_id from block when full page cache(FPC) is enable. If FPC is enable then you can’t get customer id from block just because magento2 reset all customer session. You can get customer session data if your layout set cacheable=”false” in that case magento2 just ignore cache whole page. How? lets dive.

If you open vendor/magento/module-customer/Model/Layout/DepersonalizePlugin.php


/**
 * After generate Xml
 *
 * @param \Magento\Framework\View\LayoutInterface $subject
 * @param \Magento\Framework\View\LayoutInterface $result
 * @return \Magento\Framework\View\LayoutInterface
 */
public function afterGenerateXml(\Magento\Framework\View\LayoutInterface $subject, $result)
{
    if ($this->depersonalizeChecker->checkIfDepersonalize($subject)) {
        $this->visitor->setSkipRequestLogging(true);
        $this->visitor->unsetData();
        $this->session->clearStorage();
        $this->customerSession->clearStorage();
        $this->session->setData(\Magento\Framework\Data\Form\FormKey::FORM_KEY, $this->formKey);
        $this->customerSession->setCustomerGroupId($this->customerGroupId);
        $this->customerSession->setCustomer($this->customerFactory->create()->setGroupId($this->customerGroupId));
    }
    return $result;
}

Now check the if condition, basically this return true/false from following function
vendor/magento/module-page-cache/Model/DepersonalizeChecker.php


/**
 * Check if depersonalize or not
 *
 * @param \Magento\Framework\View\LayoutInterface $subject
 * @return bool
 * @api
 */
public function checkIfDepersonalize(\Magento\Framework\View\LayoutInterface $subject)
{
    return ($this->moduleManager->isEnabled('Magento_PageCache')
        && $this->cacheConfig->isEnabled()
        && !$this->request->isAjax()
        && ($this->request->isGet() || $this->request->isHead())
        && $subject->isCacheable());
}

Here $subject->isCacheable() return false if your layout has ‘cacheable=”false”‘ attribute, lets check
vendor/magento/framework/View/Layout.php


/**
 * Check is exists non-cacheable layout elements
 *
 * @return bool
 */
public function isCacheable()
{
    $this->build();
    $cacheableXml = !(bool)count($this->getXml()->xpath('//' . Element::TYPE_BLOCK . '[@cacheable="false"]'));
    return $this->cacheable && $cacheableXml;
}

So if full page cahce enable and cacheable=”false” is not exist then magento 2 reset customer session by


$this->session->clearStorage();
$this->customerSession->clearStorage();

That’s why if you try to get customer session data from block, it’s return always empty basically only group_id is present in customer session data.

So how to get customer information then.

You can follow Magento2 official tutorial.

Now Today I discuss how you can get customer_id if cache enable. Lets dive.

Suppose vendor name ‘SR‘ and module name ‘CustomerSession

Create a contex class [SR/CustomerSession/Model/Customer/Context.php]


namespace SR\CustomerSession\Model\Customer;

class Context
{
    /**
     * Customer authorization cache context
     */
    const CONTEXT_CUSTOMER_ID = 'logged_in_customer_id';
}

Now pluginize Magento\Framework\App\Action\AbstractAction dispatch method.
So create a di.xml [SR/CustomerSession/etc/frontend/di.xml]


<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\App\Action\AbstractAction">
        <plugin name="sr-customer-app-action-dispatchController-context-plugin" type="SR\CustomerSession\Plugin\App\Action\Context" sortOrder="15"/>
    </type>
</config>

Now create SR/CustomerSession/Plugin/App/Action/Context.php


namespace SR\CustomerSession\Plugin\App\Action;

use SR\CustomerSession\Model\Customer\Context as CustomerSessionContext;

class Context
{
    /**
     * @var \Magento\Customer\Model\Session
     */
    protected $customerSession;

    /**
     * @var \Magento\Framework\App\Http\Context
     */
    protected $httpContext;

    /**
     * @param \Magento\Customer\Model\Session $customerSession
     * @param \Magento\Framework\App\Http\Context $httpContext
     */
    public function __construct(
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Framework\App\Http\Context $httpContext
    ) {
        $this->customerSession = $customerSession;
        $this->httpContext = $httpContext;
    }

    /**
     * @param \Magento\Framework\App\ActionInterface $subject
     * @param callable $proceed
     * @param \Magento\Framework\App\RequestInterface $request
     * @return mixed
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function aroundDispatch(
        \Magento\Framework\App\ActionInterface $subject,
        \Closure $proceed,
        \Magento\Framework\App\RequestInterface $request
    ) {
        $customerId = $this->customerSession->getCustomerId();
        if(!$customerId) {
            $customerId = 0;
        }

        $this->httpContext->setValue(
            CustomerSessionContext::CONTEXT_CUSTOMER_ID,
            $customerId,
            false
        );

        return $proceed($request);
    }
}

That’s it. Now you can able to get customer id following way even cache enable:


/**
* @var \Magento\Framework\App\Http\Context
*/
$this->httpContext->getValue(SR\CustomerSession\Model\Customer\Context::CONTEXT_CUSTOMER_ID);

Download full module from here

2 thoughts on “How to get customer id from block when full page cache enable in magento 2

  1. Hi Sohel,

    Thanks! This works great we have implemented this in our pricing module. Can you think of any disadvantage by implementing this method to get customer session data?

    Kind regards

    Erica

    1. Hi Erica,

      You can use it in your module without any doubt. It’s great solution over FPC and Varnish cache.

      Thanks!
      Sohel Rana

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s