Magento2 – How to Show and Delete History of Products Viewed by Logged In Customer

magento2magento2.1.5

What I have tried till now is

$objManager = \Magento\Framework\App\ObjectManager::getInstance();
$visitors = $objManager->get('Your\Store\Block\Customer\Login');
$currVisitorId = $visitors->getLoggedInUserId();
$currVisitorName = $visitors->getLoggedInUserName();

$prodMyViewedCol = $objManager->get('\Magento\Reports\Model\ResourceModel\Event\Collection');
$prodMyViewedCol->setOrder('logged_at','DESC');

$prodViewedThisEntirelyIdCol = array();  //used to store products viewed by currently logged in user.

foreach($prodMyViewedCol as $prod){
    //subject id is the column name in the event table
    if($prod->getSubjectId() != $currVisitorId){
        continue;
    }
    $product_id = $prod->getObjectId();
    $prodViewedThisEntirelyIdCol[] = $product_id;
}
echo "<pre>";
echo 'logged in user: ', $currVisitorName, '<br>';
var_dump(array_unique($prodViewedThisEntirelyIdCol));
die();

fetched the collection of events of product view and sort them in descending order.
Then after filtered them by the customer id. I'm getting the correct history which is shown below:enter image description here

Ok, I got the history and can list the history of a customer, I could be happy if my requirements were limited to this. But I need to delete the history. I can do that as well but deleting the data in table will hamper the results of reports in backend.

So what I want is: get the products viewed by currently logged in customer and delete that history safely without hampering the core behavior of reports, or store's database.

Best Answer

First off: don't directly use the object manager in your code, but use dependency injection.

enter image description here

Secondly: use factories to create instances of objects.

And for the question about deletion: you should use Service Contracts (repositories) when it comes to handling the persistence of data. Given that the reports-module currently doesn't have any (2.1.6), you need to handle the deletion using the resource model. Once again: use dependency injection and a factory to get this model.

Example code for a Block class:

namespace yourNameSpace;
class Example  extends \Magento\Framework\View\Element\Template
{
    /**
     * @var \Magento\Reports\Model\ResourceModel\Event\CollectionFactory
     */
    protected $collectionFactory;
/**
 * @var \Magento\Customer\Model\Session
 */
protected $customerSession;

/**
 * @var \Magento\Reports\Model\ResourceModel\EventFactory
 */
protected $resourceFactory;

/**
 * Example constructor.
 * @param \Magento\Reports\Model\ResourceModel\Event\CollectionFactory $collectionFactory
 * @param \Magento\Reports\Model\ResourceModel\EventFactory $resourceFactory
 * @param \Magento\Customer\Model\Session $customerSession
 */
public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,        
    \Magento\Reports\Model\ResourceModel\Event\CollectionFactory $collectionFactory,
    \Magento\Reports\Model\ResourceModel\EventFactory $resourceFactory,
    \Magento\Customer\Model\Session $customerSession
) {
    parent::__construct($context);
        $this->collectionFactory = $collectionFactory;
        $this->customerSession = $customerSession;
        $this->resourceFactory = $resourceFactory;
    }

    /**
     * @return bool|\Magento\Reports\Model\ResourceModel\Event\Collection
     */
    public function getViewedProductsForCurrentCustomer()
    {
        if ($this->customerSession->isLoggedIn()) {
            /** @var \Magento\Reports\Model\ResourceModel\Event\Collection $collection */
            $collection = $this->collectionFactory->create();
            $collection->addFieldToFilter('subject_id', $this->customerSession->getCustomerId());
            $collection->distinct(true);

            return $collection;
        }

        return false;
    }

    /**
     * 
     */
    public function deleteViewedProductsForCurrentCustomer()
    {
        if ($products = $this->getViewedProductsForCurrentCustomer()) {
            /** @var \Magento\Reports\Model\ResourceModel\Event $resource */
            $resource = $this->resourceFactory->create();
            foreach($products as $product) {
                $resource->delete($product);
            }
        }
    }
}

Haven't tested this code, but in theory it should work.

On a sidenote: I don't know how much knowledge you have about Magento 2, but you should really understand the following core concepts:

  • Dependency Injection
  • Repositories
  • Auto generated code (factories)

The Magento documentation has tons of examples about this. Besides that it will also help to dive in the following programming principles:

  • S.O.L.I.D programming
  • Composition over Inheritance
Related Topic