3

I want to add some link to navigation menu in magento 2. Some link will display after checking customer logged in or not. I tried to create a plugin.

namespace AIS\Custom\Plugin;

use Magento\Framework\Data\Tree\NodeFactory;

class Topmenu
{
    protected $nodeFactory;
    protected $customerSession;

    public function __construct(
        \Magento\Customer\Model\Session $customerSession,
        NodeFactory $nodeFactory
    ) {
        $this->customerSession = $customerSession;
        $this->nodeFactory = $nodeFactory;
    }

    public function beforeGetHtml(
        \Magento\Theme\Block\Html\Topmenu $subject,
        $outermostClass = '',
        $childrenWrapClass = '',
        $limit = 0
    ) {
        $node = $this->nodeFactory->create(
            [
                'data' => $this->getProviderNode(),
                'idField' => 'id',
                'tree' => $subject->getMenu()->getTree()
            ]
        );
        $subject->getMenu()->addChild($node);

        if($this->customerSession->isLoggedIn()) {
            $node = $this->nodeFactory->create(
                [
                    'data' => $this->getMyCourseNode(),
                    'idField' => 'id',
                    'tree' => $subject->getMenu()->getTree()
                ]
            );
            $subject->getMenu()->addChild($node);
        }
    }

    protected function getProviderNode()
    {
        return [
            'name' => __('Provider'),
            'id' => 'nav-provider',
            'url' => 'http://www.example.com/',
            'has_active' => false,
            'is_active' => false // (expression to determine if menu item is selected or not)
        ];
    }

    protected function getMyCourseNode()
    {
        return [
            'name' => __('My Course'),
            'id' => 'nav-mycourse',
            'url' => 'http://www.example.com/',
            'has_active' => false,
            'is_active' => false // (expression to determine if menu item is selected or not)
        ];
    }

    protected function getCacheLifetime()
    {
        return 0;
    }
}

All page seems fine but the home page is not following the checking. It will display "My Course" button after customer logout. I try to disable the cache and it cannot fix the problem.

1
  • Finally I aborted to use Plugin to do this. I try to override Topmenu Block and set the cache life time to 1 and it is success. Thanks.
    – Haze
    Oct 25, 2017 at 8:03

5 Answers 5

1

You can use alternative sample code as below.

$ObjectManager= \Magento\Framework\App\ObjectManager::getInstance();
$context = $ObjectManager->get('Magento\Framework\App\Http\Context');
$isLoggedIn = $context->getValue(\Magento\Customer\Model\Context::CONTEXT_AUTH);
return $isLoggedIn;

Above is reference code only. You can inject \Magento\Framework\App\Http\Context in your constructor instead of \Magento\Customer\Model\Session

1
  • 1
    Sorry, it still not do the checking in homepage. I think it is about the cache but I have no idea.
    – Haze
    Oct 25, 2017 at 4:16
1

Magento\Customer\Model\Session doesn't work properly if cache is enabled. So You have to set cacheable="false" or keep cache disabled in order to use Magento\Customer\Model\Session in your constructor.

You can use below method instead. This will work even if your cahce is enabled.

protected $_customerSession;

public function __construct(
    \Magento\Customer\Model\SessionFactory $customerSession
) 
{
    $this->_customerSession = $customerSession;
}
...
...

$customer = $this->_customerSession->create();
if($customer->isLoggedIn){
    echo "customer is logged in";
}
1

Add this code after

$subject->setCacheable(false); 

In if($this->customerSession->isLoggedIn()) {

BY flush cache after logout

Another good idea to flush block cache after logout.

Fire an event on controller_action_postdispatch_customer_account_logout

<?php
namespace [Vendorname]\[ModuleName]\Observer;
use Magento\Framework\Event\ObserverInterface;
/**
 * @category   Devamitbera
 * @author     Amit Bera <[email protected]>
 * @website    http://www.amitbera.com
* @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
class [MyObserverClass]  implements ObserverInterface
{

    protected $_cacheTypeList;

    public function __construct(
        \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
    ) {

        $this->_cacheTypeList = $cacheTypeList;
    }
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        /* Block cache flush */
        $this->_cacheTypeList->cleanType('block_html');

        $this->_cacheTypeList->cleanType('customer_notification');
        /* Full page cache  flush */
        $this->_cacheTypeList->cleanType('full_page');

        return $this;
    }


}
1
  • thanks for your help but it still not working
    – Haze
    Oct 25, 2017 at 4:31
1

Following code worked for me:

Use \Magento\Framework\App\Http\Context class to get value for \Magento\Customer\Model\Context::CONTEXT_AUTH. After that overwrite \Magento\Theme\Block\Html\Topmenu::getCacheKeyInfo() to add information about logged customer to block's cache key info (or create plugin):

public function getCacheKeyInfo()
{
   $keyInfo = parent::getCacheKeyInfo();
   $keyInfo[] = $this->httpContext->getValue(\Magento\Customer\Model\Context::CONTEXT_AUTH);
   return $keyInfo;
}
0

Use Factory class.

/**
 * @var \Magento\Customer\Model\SessionFactory
 */
protected $customerSessionFactory;

public function __construct(
    ....
    \Magento\Customer\Model\SessionFactory $customerSessionFactory
    ....
) 
{
    ....
    $this->customerSessionFactory = $customerSessionFactory;
    ....
}

public function yourFunctionName(){
  ...
  $customerSession = $this->customerSessionFactory->create();
  $customerId = $customerSession->getCustomer()->getId();
  $isLoggedIn = $customerSession->isLoggedIn();
  ...
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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