2

Magento 2 get recently viewed products collection of Customer (Using customer ID) programmatically

I tried this solution But I want recently viewed products collection.

I tried below solution too but it is not returning anything. [I am logged in]

protected $recentlyViewed;

public function __construct(
...
    \Magento\Reports\Block\Product\Viewed $recentlyViewed
) {
...
    $this->recentlyViewed = $recentlyViewed;
}

/**
 * Get recently viewed products for the customer
 *
 */
public function getMostRecentlyViewed(){
    return $this->recentlyViewed->getItemsCollection();
}
5
  • I added code in chat box. Commented Nov 26, 2018 at 17:27
  • Hey Adi... Did you get the Recently View Product Collection??? I also tried all the techniques given below but returning me Null Array
    – Asad Khan
    Commented Jun 20, 2019 at 6:02
  • No I never get that one, Yeah none of answers worked for me @AsadKhan Commented Jun 21, 2019 at 16:55
  • 1
    OK Sir actually I get the recently viewed products.... If u still need it then I'm gonna post the code... n also I set it for those customers as well who r not logged In...
    – Asad Khan
    Commented Jun 22, 2019 at 17:06
  • sure sure you can post it :) If it works I'll accept as answer @AsadKhan Commented Jun 23, 2019 at 17:20

6 Answers 6

5

Try to use this code :

Method 1 :

/**
 * Layout
 * @var \Magento\Framework\View\LayoutInterface
 */

 protected $_layout;

 public function __construct(
    .....
    \Magento\Framework\View\LayoutInterface $layout
    .......
 ) {
     $this->_layout = $layout;
 }

public function getMyCollection() {
    $block =  $this->_layout->getBlockSingleton(\Magento\Reports\Block\Product\Viewed::class)->getItemsCollection();
    return $block;
}

UPDATE :

Method 2 :

You need to load ItemCollection() after get collection like below way :

protected $recentlyViewed;

public function __construct(
    \Magento\Reports\Block\Product\Viewed $recentlyViewed
) {
    $this->recentlyViewed = $recentlyViewed;
}

public function execute() {
    $collection = $this->recentlyViewed->getItemsCollection()->load();
    echo "<pre>";
    print_r($collection->getData());
    exit;
}

Reference

10
  • 1
    Thanks bro :) Definitely try this tomorrow morning ! Commented Nov 25, 2018 at 14:00
  • 1
    Sure :) If not working then you can update here.. Commented Nov 25, 2018 at 14:02
  • Not working @Rohan Commented Nov 26, 2018 at 5:43
  • 1
    Try to use this second method.. it's working from my side so. Commented Nov 26, 2018 at 6:18
  • Okay bro :) trying * Commented Nov 26, 2018 at 6:19
2

Please try below code, I tested the same and found it working:

<?php 
namespace YourPackage\YourModule\Block\RecentlyViewed;

class Test extends \Magento\Framework\View\Element\Template
{
    protected $recentlyViewed;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Magento\Reports\Block\Product\Viewed $recentlyViewed,
        array $data = []
    ) {
        $this->recentlyViewed = $recentlyViewed;
        parent::__construct( $context, $data );
    }

    public function getMostRecentlyViewed(){
        return $this->recentlyViewed->getItemsCollection()->getData();
    }
}

and call this block in required file, cms page or static block, for example if you wan to add this block to home page than add below code:

{{block class="YourPackage\YourModule\Block\RecentlyViewed\Test" name="block_recently_viewed" template="YourPackage_YourModule::test.phtml"}}

In test.phtml file you can get the collection and design it in your way, I just tested by printing the collection and it was printing correctly.

test.phtml

<?php echo "<pre>"; print_r($this->getMostRecentlyViewed()); ?>

Note : Please note that the collection will be empty if you don't visits any page as the collection is of recently viewed product by you. Visit some products at your store and you will get the collection being populated.

13
  • Is it possible without accessing parent ? Commented Nov 26, 2018 at 5:43
  • without extends \Magento\Framework\View\Element\Template Commented Nov 26, 2018 at 5:43
  • No, it would create issue as we need to Abstract class for frontend representational purpose :), We need to create similar abstract class if you don't want to extend it but that is meaningless effort. Its good to extend the existing available Abstract class.. Commented Nov 26, 2018 at 5:59
  • Okay and If i extend that class _ I want customers collection Commented Nov 26, 2018 at 6:00
  • And I want all this in Model file that's why I asked that I need collection for that :) Commented Nov 26, 2018 at 6:01
2

so In my scenario I need Recently Viewed Products in new custom page... n I also want to show the recently viewed products while the user is not logged In.

Vender/Module/view/frontend/layout/recently_index_index

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <referenceContainer name="content">
        <block class="Vender\Module\Block\Viewedd" name="recently" template="Vender_Module::recently.phtml" cacheable="false" />
    </referenceContainer>
</page>

Ok so this layout is really important in this layout as you can see that cacheable = "false" this is the thing where I was stuck around 3 days. If you want to show Recently Viewed Products If the user is not logged In then you have to false the cacheable. now

Vender\Module\Block\Viewedd.php

<?php
namespace Vender\Module\Block;


use Magento\Framework\View\Element\Template\Context;
use Magento\Reports\Block\Product\Viewed;
use Magento\Catalog\Model\ProductFactory;

class Viewedd extends \Magento\Framework\View\Element\Template
{
    /**
     * Limit of orders
     */
    const ORDER_LIMIT = 4;  //Image Limit this can be changed from here


    /**
     * @param \Magento\Framework\View\Element\Template\Context $context
     * @param array $data
     */
    public function __construct(
        Context $context,
        Viewed $recentlyViewed,
        ProductFactory $productFactory,
        array $data = []
    ) {
        $this->_recentlyViewed = $recentlyViewed;
        $this->_productFactory = $productFactory;
        parent::__construct($context, $data);
    }

    /**
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->getRecentlyviewed();
    }

    /**
     * Get recently placed orders. By default they will be limited by 5.
     */

    public function getRecentlyviewed()
    {

     $recentViewedCollection =  $this->_recentlyViewed->getItemsCollection()->setPageSize(
            self::ORDER_LIMIT
        )->load();
     ;
        $this->setRecentlyviewedcol($recentViewedCollection);
        return $this->getRecentlyviewedcol();
    }


    /**
     * @return string
     */
    protected function _toHtml()
    {
        if ($this->getRecentlyviewedcol()->getSize() > 0) {
            return parent::_toHtml();
        }
       return parent::_toHtml();
    }

    public function getProductLoader()
    {
        return $this->_productFactory;
    }

}

now in this class as you can see first we get recently viewed Products in getRecentlyviewed() function. now after that we need to create our phtml file

Vender/Module/view/frontend/templates/recently.phtml

<h1>Recently Viewed Products</h1>

<?php
$col = $this->getRecentlyviewedcol();
$count = count($col);
$_productloader = $this->getProductLoader();
?>

<?php if($count): ?>         
    <div class="wishtlist-recently-viewed">
        <div class="d-recently-title">
            <h3>Recently Viewed</h3>
        </div>
        <div class="d-view-blocks">
            <ul>
                <?php foreach ($col as $item) : ?> 
                    <?php        
                        $loadedProduct = $_productloader->create()->load($item->getEntityId());
                        $i = $this->helper('Magento\Catalog\Helper\Image')->init($loadedProduct, 'product_page_image_large'); 
                    ?>
                <li class="col-12 col-lg-3 col-md-3 col-sm-12">
                    <div class="d-slide-box">
                        <div class="d-block-div ">
                            <div class="d-wishlist-img">
                                <a href="<?=$loadedProduct->getProductUrl();?>"><img style="width:300px;height:350px;" class="img-fluid" src="<?=$i->getUrl();?>" alt="First slide"></a>
                            </div>
                            <div class="d-view-title-inner d-view-title-inner-r-v">
                            <div class="d-wishlist-title">
                                <a href="<?=$loadedProduct->getProductUrl();?>"><h3><?=$loadedProduct->getName()?></h3></a>
                            </div>

                            </div>

                        </div>
                    </div>
                </li>
                <?php endforeach; ?>
            </ul>
        </div>
    </div>
<?php endif;?>

In this you'll get all the Recently Viewed Products with images and with Product Name.
Note: firstly I was trying this on the HomePage using the above other solutions but it was not working you need to create new layout or maybe put the xml block in your Layout hope it will work for you.

4
  • It's not giving collection for the guest users. Showing only if I login. Any solution please?
    – m2dev
    Commented Dec 8, 2023 at 10:22
  • have you add cacheable="false" in you Layout?
    – Asad Khan
    Commented Dec 8, 2023 at 12:04
  • No can't add it
    – m2dev
    Commented Dec 8, 2023 at 12:33
  • I have to make it working without adding cacheable="false"
    – m2dev
    Commented Dec 8, 2023 at 12:42
1
\Magento\Reports\Model\ResourceModel\Product\CollectionFactory $_reportCollectionFactory
$this->_reportCollectionFactory = $_reportCollectionFactory;

$collection = $this->_reportCollectionFactory->create()
        ->addAttributeToSelect('*')
        ->addViewsCount()
        ->setStoreId($storeId)
        ->addStoreFilter($storeId)
        ->setPageSize(10); 
1

I have use this same solution and first time I am not getting any items in recently viewed products collection.

After that I have checked and enable reports events from backend.

Stores=>congratulations=>general=>reports=>set yes in drop-down and also make sure that product view event is enable.

This solution working for me and my project on magento 2.3.4 version. And if still you don't get items then you can try by adding cacheable= "false" in your layout block.

Thank you.

0
<?php

 declare(strict_types=1);

 namespace Lax\Catalog\Block\Product\ProductList;

use Magento\Catalog\Block\Product\AbstractProduct;
use Magento\Catalog\Block\Product\Context;
use Magento\Framework\DataObject\IdentityInterface;
use Magento\Customer\Model\Session;
use Magento\Customer\Model\Visitor;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;

class Recentproductview extends AbstractProduct implements IdentityInterface
{
/**
 * @var Session
 */
private $session;

/**
 * @var Visitor
 */
private $visitor;

/**
 * @var Context
 */
private $context;

/**
 * @var CollectionFactory
 */
private $productCollectionFactory;


/**
 * @param Context $context
 * @param Session $session
 * @param Visitor $visitor
 * @param CollectionFactory $productCollectionFactory
 * @param array $data
 */
public function __construct(
    Context $context,
    Session $session,
    Visitor $visitor,
    CollectionFactory $productCollectionFactory,
    array $data = []
) {
    $this->session = $session;
    $this->visitor = $visitor;
    $this->productCollectionFactory = $productCollectionFactory;
    parent::__construct($context, $data);
}

/**
 * Prepare data
 *
 * @return $this
 */
protected function _prepareData()
{
    $customerId = $this->session->getCustomerId();
    $visitorId = $this->visitor->getId();
    
    if ($customerId) {
        $customerWhere = " and customer_id =  $customerId ";
    } elseif ($visitorId) {
        $customerWhere = " and visitor_id =  $visitorId ";
    } else {
        $customerWhere = ' and customer_id = NULL and visitor_id = NULL ';
    }
    
    $currentProductId = $this->getProduct()->getEntityId() ;
    $typeId = 'recently_viewed_product';
    $lifeTime = 1000;

    $joinConditions = 'e.entity_id = catalog_product_frontend_action.product_id';
    $collection = $this->productCollectionFactory->create();
    $collection->addMinimalPrice()
        ->addFinalPrice()
        ->addTaxPercents()
        ->addAttributeToSelect('*');
    $collection->getSelect()->join(
        ['catalog_product_frontend_action'],
        $joinConditions,
        []
        )->columns("catalog_product_frontend_action.added_at")
        ->where("catalog_product_frontend_action.product_id != $currentProductId and 
         catalog_product_frontend_action.type_id =  '$typeId'  
         $customerWhere and 
         catalog_product_frontend_action.added_at > ".(time() - $lifeTime));
    $collection->addAttributeToFilter('visibility', \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
        ->setPageSize('20')
        ->getSelect()->order('catalog_product_frontend_action.added_at DESC');
       //  echo  $collection->getSelect();
    $this->_itemCollection = $collection->load();
    // end
   
    foreach ($this->_itemCollection as $product) {
        $product->setDoNotUseCategoryId(true);
    }

    return $this;
}

/**
 * Before to html handler
 *
 * @return $this
 */
protected function _beforeToHtml()
{
    $this->_prepareData();
    return parent::_beforeToHtml();
}

/**
 * Get collection items
 *
 * @return Collection
 */
public function getItems()
{
    /**
     * getIdentities() depends on _itemCollection populated, but it can be empty if the block is hidden
     * @see https://github.com/magento/magento2/issues/5897
     */
    if ($this->_itemCollection === null) {
        $this->_prepareData();
    }
    return $this->_itemCollection;
}

/**
 * Return identifiers for produced content
 *
 * @return array
 */
public function getIdentities()
{
    $identities = [];
    foreach ($this->getItems() as $item) {
        $identities[] = $item->getIdentities();
    }
    return array_merge([], ...$identities);
}

/**
 * Find out if some products can be easy added to cart
 *
 * @return bool
 */
public function canItemsAddToCart()
{
    foreach ($this->getItems() as $item) {
        if (!$item->isComposite() && $item->isSaleable() && !$item->getRequiredOptions()) {
            return true;
        }
    }
    return false;
}

}

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.