0

I have modified a themes account_links.phtml file. Client has requested that it just says "Login" and if logged in it should just show "My Account".

This is the code I came up with:

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$customerSession = $objectManager->get('Magento\Customer\Model\Session');

?>
<div id="header-account" class="account-links top-links links-wrapper-separators-left skip-content skip-content--style">
    <?php if ($customerSession->isLoggedIn()): ?>

        <ul class="header links">
            <li class="authorization-link" data-label="or">
                <a href="<?php echo $block->getUrl('customer/account') ?>">My Account</a>
            </li>
        </ul>

    <?php else: ?>
        <ul class="header links">
            <li class="authorization-link" data-label="or">
                <a href="<?php echo $block->getUrl('customer/account/login') ?>">Login</a>
            </li>
        </ul>
    <?php endif; ?>
</div>

This works if the cache is disabled but if cache is enabled then it always shows "Login".

How do I make it so that this isn't broken by the cache as site needs the cache enabled.

Guerrilla
  • 187
  • 2
  • 13
  • You might find this to be helpful https://magento.stackexchange.com/questions/91897/how-to-check-if-customer-is-logged-in-or-not-in-magento-2 – paj Jul 10 '17 at 20:38
  • I used the code in that example and it doesnt work with cache, this is why I make this post because that thread does not address the cache issue. – Guerrilla Jul 10 '17 at 20:41
  • I added an answer with some code that I use for this. Best not to access the objectmanager in your template, the Magento Police will slap your fingers... :) – paj Jul 10 '17 at 21:08
  • Do not use object manager in template file. – benmarks Jul 11 '17 at 12:48
  • Your example isn't working because the objectmanager call should be $customerSession = $objectManager->create('Magento\Customer\Model\Session'); – paj Jul 11 '17 at 14:49

2 Answers2

2

In your module create a helper class and query this from your template. This should work with all caches enabled.

template

   <?php

       $_helper = $this->helper('MyModule\Page\Helper\Data');
       $_loggedIn=false;

       if ($_helper->isLoggedIn()) {

            $_loggedIn=true;
       }
    ?>

    <div>

    <?php if ($_loggedIn): ?>
    logged in
    <php endif; ?

    </div>

helper Data.php

<?php
namespace MyModle\Page\Helper;

use Magento\Framework\App\Helper\AbstractHelper;

class Data extends AbstractHelper
{
    /**
     * @var \Magento\Framework\App\Http\Context
     */
    private $httpContext;

    public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        \Magento\Framework\App\Http\Context $httpContext
    ) {
        parent::__construct($context);
        $this->httpContext = $httpContext;
    }

    public function isLoggedIn()
    {
        // https://magento.stackexchange.com/a/171126/7863
        //
        $isLoggedIn = $this->httpContext->getValue(\Magento\Customer\Model\Context::CONTEXT_AUTH);
        return $isLoggedIn;
    }
}
paj
  • 5,785
  • 5
  • 21
  • 43
  • Thank you very much I will try this. Does this have to be as a module or can it be inside the template? – Guerrilla Jul 10 '17 at 21:56
  • 1
    This does nothing to address the issue of the data getting stuck in Magento's caches. – Ryan Hoerr Jul 10 '17 at 23:00
  • @RyanHoerr as I stated in the answer this method does not get cached. The question was about detecting login status, the cache problem was a symptom of the OP's first solution. – paj Jul 11 '17 at 09:15
  • @Guerrilla template logic should be performed in a module. – paj Jul 11 '17 at 09:16
  • @paj Respectfully, there is no way that is correct when Full Page Cache is in the picture. I don't see that you're doing anything except moving the login check from the template into a helper (which is better, but again, does not address the fundamental problem). You can't have a template output anything user-specific while FPC is enabled for a page. – Ryan Hoerr Jul 11 '17 at 12:11
  • @RyanHoerr maybe you should test it yourself, I have Mage 2.1.7 with all caches enabled including FPC with Varnish and the cache correctly caches the logged in / not logged in pages when using this code and even the (correct) session code from the OP's question. Happy to send you a link to my dev site to test it yourself. – paj Jul 11 '17 at 14:53
  • @paj do you get the X-Magento-Cache-Debug: HIT debug header? I found that if any block on site has cacheable=false the it looks like the FPC is working but actually it is being bypasses because of a non cachable block – Guerrilla Jul 11 '17 at 16:53
  • 1
    @Guerrilla yes X-Magento-Cache-Debug:HIT when logged in and logged out. – paj Jul 12 '17 at 09:07
  • @paj I tried this code and it works but for some reason now it gives X-Magento-Cache-Debug:MISS when user is logged in. I am not sure why but it functions correctly although I would prefer certain pages to be cached even for logged in users. I am not sure how to control that. – Guerrilla Jul 16 '17 at 05:54
  • 1
    @paj it was because page wasnt generated in cache, i refreshed it and it is actually HIT. Thanks for the help. The Magento cache must be clever enough to detect changes when its done in helper. I wish they had it properly documented. – Guerrilla Jul 16 '17 at 06:05
  • 1
    I just noticed that this doesnt work. If someone views pages logged in and then logs out the pages they viewed still show them as logged in – Guerrilla Aug 14 '17 at 13:37
2

The most reliable way to avoid caching problems like this is to move the logic entirely onto the client side (in JavaScript). This is how Magento 2 handles all user-specific data: It renders the page with generic data, then fills in user-specific data (like the header account info) with JS, AJAX requests, and local storage of session data. The same is true for account pages, cart, and checkout.

This approach is more complex, it requires knowledge of a lot more of Magento's layers, but it is the only way to accomplish what you want, cleanly, without intentionally disabling caching in one way or another.

You can find a basic rundown of this approach for what you're trying to do in this answer by 10basetom: https://magento.stackexchange.com/a/171954/1905

This information may also be helpful: How to check that customer is logged in on frontend in Magento 2.1?

And for basic info on Magento's JS system in general, see the dev docs: http://devdocs.magento.com/guides/v2.1/javascript-dev-guide/javascript/js_init.html

Ryan Hoerr
  • 12,271
  • 7
  • 47
  • 54
  • Hi Ryan, thanks for your reply. Using javascript makes sense. I read through the javascript page you linked and it makes sense. I will explore the customer-data module and see if I can get that to work. I must admit the magento docs seem a bit incomplete, I can't see any documentation for any of their modules. Is it just a case of looking through them and figuring it out? – Guerrilla Jul 11 '17 at 01:04