magento2: Cant't get cart items in block - quote object empty

Preconditions

  1. Magento 2.1 CE, php 7.0

Steps to reproduce

  1. In custom module I added block, which should check if provided product is in cart.
  2. Block is added properly, although method doesn’t work.
  3. When I try to check if my product is in cart I get info that cart is empty (but in fact it is not). That is my class:

namespace [vendor]\SkinHelper\Block\Catalog\Product;

use \Magento\Catalog\Api\Data\ProductInterface;
use \Magento\Checkout\Model\Session;
use \Magento\Framework\View\Element\Template;
use \Magento\Framework\View\Element\Template\Context;

/** Class provides method to check if given product is in cart
 * @universal
 */
class IsInCart extends Template
{

    /**
     * @var \Magento\Checkout\Model\Session
     */
    private $checkoutSession;



    /**
     * Di.
     * @param \Magento\Checkout\Model\Session $checkoutSession
     * @param \Magento\Framework\View\Element\Template\Context $context
     * @param array $data
     */
    public function __construct(
        Session $checkoutSession,
        Context $context,
        array $data
    )
    {
        parent::__construct($context, $data);

        $this->checkoutSession = $checkoutSession;
    }



    /**
     * Method check if provided product is in cart of current customer.
     * Doesn't work dynamically.
     * TODO: There is a bug actually in magento connected with session and full page cache
     * TODO: More details: https://github.com/magento/magento2/issues/3294
     *
     * @param \Magento\Catalog\Api\Data\ProductInterface $product
     *
     * @return bool $inCart
     */
    public function isInCart(ProductInterface $product)
    {
        $productId = $product->getId();
        $cartItems = $this->checkoutSession->getQuote()->getAllVisibleItems();
        $itemsIds = array();
        foreach ($cartItems as $cartItem) {
            $itemsIds[] = $cartItem->getProduct()->getId();
        }

        return in_array($productId, $itemsIds);
    }


    /**
     * Method counts items now available in cart.
     * TODO: There is a bug actually in magento connected with session and full page cache
     * TODO: More details: https://github.com/magento/magento2/issues/3294
     *
     * @return int $cartDataCount
     */
    public function countItemsInCart()
    {
        $cartItems = $this->checkoutSession->getQuote()->getAllVisibleItems();
        $cartItemsCount = count($cartItems);

        return $cartItemsCount;
    }
  1. That’s my call for these methods:

`<?php echo $block->isInCart($_product); ?>

<?php echo $this->helper([vendor]\SkinHelper\Helper\Test')->isInCart($_product) ?>`

As you can see I was trying the same thing with helper (called from helper), but it failed.

  1. I was trying also the same way on \Magento\Checkout\Model\Cart and it also didn’t worked.
  2. The strangest thing is that the same logic placed and called as controller (by url) works and returns correct output.

Expected result

  1. Of course, method in block called inside template returns correct result.

Actual result

  1. When I dump $itemsIds it is empty, so no elements can be retrieved. Products are present in minicart, as well as in quote table as well.
  2. Method works in controller but not inside block or helper called from template. What is even more strange the same method in helper called from controller works.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 25 (11 by maintainers)

Most upvoted comments

I think problem may lay in cache, especially Full page cache.

@bartek9007 the general rule is to move private content in browser. When Magento renders public content (should not contain any personal data), it removes everything from session in order to prevent information leaks.

Take a look on this - http://devdocs.magento.com/guides/v2.1/config-guide/cache/cache-priv-priv.html. “Customer data sections” is preferable way to achieve your goal. If you don’t want to rewrite your code to JS, you can try deprecated approach - mark your block as private using _isScopePrivate property. This will tell Magento to load content using separate AJAX call. In this case cache will be invalidated on any POST request.

you need to add cacheable=“false” in layout xml to access cart quote in custom module