How to check if customer is logged in or not?

Important reminder: One should never call the Object Manager directly

Thus here's how to do it the clean way

In any class except templates

You first need to inject the following class in your constructor: /Magento/Customer/Model/Session :

protected $_customerSession;    // don't name this `$_session` since it is already used in \Magento\Customer\Model\Session and your override would cause problems

public function __construct(
    ...
    \Magento\Customer\Model\Session $session,
    ...
) {
    ...
    $this->_customerSession = $session;
    ...
}

Then in your class you can call the following:

if ($this->_customerSession->isLoggedIn()) {
    // Customer is logged in 
} else {
    // Customer is not logged in
}

In a template

It requires a bit more work in a template as you will have to setup a preference for the block that renders the template to do that the clean way:

<preference for="Block\That\Renders\The\Template"
            type="Vendor\Module\Block\Your\Custom\Block" />

Then in your custom block contrusctor you need to following the same dependency injection as for any class (explained above).

The extra step here is to create a public method that can be used in your template to check whether a customer is logged in or not

public function isCustomerLoggedIn()
{
    return $this->_customerSession->isLoggedIn();
}

Then in your template you can call:

if ($block->isCustomerLoggedIn()) {
    // Customer is logged in
} else {
    // Customer is not logged in
}

Alternative if the customer session is not initialized yet

There's another way of doing it which implies using Magento\Framework\App\Http\Context instead of Magento/Customer/Model/Session

Then you can call $this->_context->getValue(\Magento\Customer\Model\Context::CONTEXT_AUTH) instead of $this->_customerSession->isLoggedIn() to check whether the customer is logged in or not.

However this method may give you different results, I suggest you read this great answer for more information: https://magento.stackexchange.com/a/92133/2380


Following code you can check customer login or not anywhere

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$customerSession = $objectManager->get('Magento\Customer\Model\Session');
if($customerSession->isLoggedIn()) {
   // customer login action
}

From controller

$this->_objectManager->get('Magento\Customer\Model\Session');
if($customerSession->isLoggedIn()) {
   // customer login action
}

It is possible via Magento\Framework\App\Http\Context or via Magento\Customer\Model\Session. However, the result may be different:

  • HTTP context is initialized earlier than customer session (but it does not matter since both are initialized in action controllers)
  • When PageCache module is on (probably always on production), keep in mind that as soon as layout generation started, customer session will be cleared by \Magento\PageCache\Model\Layout\DepersonalizePlugin::afterGenerateXml on all cacheable pages. It means that if you now check if the customer is logged in via the HTTP context, it will still say 'yes', but customer data will not be available in customer sessions anymore. So double-check is necessary before trying to access data in customer sessions. This can easily happen in the block, while is unlikely in action controller since you are not expected to generate layout manually there, it will be generated after-action controller returns an instance of ResultInterface

To eliminate any risk of described inconsistencies when PageCache on, consider using customer session, if it is already initialized (true for action controllers). Else use the HTTP context.