cancel
Showing results for 
Search instead for 
Did you mean: 

Magento 2 - Product Reviews only by customer who purchased the product

SOLVED

Magento 2 - Product Reviews only by customer who purchased the product


I do not want the customers/guest to let post reviews who did not make a purchase of that product.
- for guest users I disable - "Allow guest to write reviews"
- for customers/logged in users - how to add condition?

 

Anyone having an extension that providing such features.

1 ACCEPTED SOLUTION

Accepted Solutions

Re: Magento 2 - Product Reviews only by customer who purchased the product

Hello @Sandip Magento

 

You have to add the condition here.
If the current customer has purchased the current product, then load the review form otherwise show the custom message or don't load any template.

Follow the steps given below

 

1. Override the Review form block with your custom block

 

app/code/Vendor/Module/etc/di.xml

 

 

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
	<preference for="Magento\Review\Block\Form" type="Vendor\Module\Block\Review\Form" />
</config>

 

2. Add condition for the customer in your custom block

 

app/code/Vendor/Module/Block/Review/Form.php

 

 

<?php

namespace Vendor\Module\Block\Review;

class Form extends \Magento\Review\Block\Form
{
	/**
     * Customer Session Factory
     *
     * @var \Magento\Customer\Model\SessionFactory
     */
	protected $_customerSession;
	/**
     * Order Collection Factory
     *
     * @var \Magento\Sales\Model\ResourceModel\Order\CollectionFactory
     */
	protected $_orderCollectionFactory;
	/**
     * Registry
     *
     * @var \Magento\Framework\Registry
     */
	protected $_registry;
	/**
     * Review data
     *
     * @var \Magento\Review\Helper\Data
     */
    protected $_reviewData = null;

    /**
     * Catalog product model
     *
     * @var \Magento\Catalog\Api\ProductRepositoryInterface
     */
    protected $productRepository;

    /**
     * Rating model
     *
     * @var \Magento\Review\Model\RatingFactory
     */
    protected $_ratingFactory;

    /**
     * @var \Magento\Framework\Url\EncoderInterface
     */
    protected $urlEncoder;

    /**
     * Message manager interface
     *
     * @var \Magento\Framework\Message\ManagerInterface
     */
    protected $messageManager;

    /**
     * @var \Magento\Framework\App\Http\Context
     */
    protected $httpContext;

    /**
     * @var \Magento\Customer\Model\Url
     */
    protected $customerUrl;

    /**
     * @var array
     */
    protected $jsLayout;

    /**
     * @var \Magento\Framework\Serialize\Serializer\Json
     */
    private $serializer;

    /**
     * Form constructor.
     *
     * @param \Magento\Framework\View\Element\Template\Context $context
     * @param \Magento\Framework\Url\EncoderInterface $urlEncoder
     * @param \Magento\Review\Helper\Data $reviewData
     * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
     * @param \Magento\Review\Model\RatingFactory $ratingFactory
     * @param \Magento\Framework\Message\ManagerInterface $messageManager
     * @param \Magento\Framework\App\Http\Context $httpContext
     * @param Url $customerUrl
     * @param array $data
     * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
     * @throws \RuntimeException
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
	public function __construct(
		\Magento\Framework\View\Element\Template\Context $context,
        \Magento\Framework\Url\EncoderInterface $urlEncoder,
        \Magento\Review\Helper\Data $reviewData,
        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
        \Magento\Review\Model\RatingFactory $ratingFactory,
        \Magento\Framework\Message\ManagerInterface $messageManager,
        \Magento\Framework\App\Http\Context $httpContext,
        \Magento\Customer\Model\Url $customerUrl,
        array $data = [],
        \Magento\Framework\Serialize\Serializer\Json $serializer = null,
		\Magento\Customer\Model\SessionFactory $customerSession,
		\Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory,
		\Magento\Framework\Registry $registry
	) {
		$this->_customerSession = $customerSession;
		$this->_orderCollectionFactory = $orderCollectionFactory;
		$this->_registry = $registry;
		parent::__construct($context, $urlEncoder, $reviewData, $productRepository, $ratingFactory, $messageManager, $httpContext, $customerUrl, $data);
		$this->jsLayout = isset($data['jsLayout']) ? $data['jsLayout'] : [];
		$this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
            ->get(\Magento\Framework\Serialize\Serializer\Json::class);
	}
	
	protected function _construct()
	{
		parent::_construct();

		if ($this->isCurrentCustomerPurchasedThisProduct()) {
			$this->setTemplate('Magento_Review::form.phtml');
		} else {
$this->setTemplate('Vendor_Module::no_review_form.phtml');
// You can set null here if you don't want to load any template
// $this->setTemplate(null); } } public function getCurrentCustomerId() { return $this->_customerSession->create()->getCustomer()->getId(); } public function getCustomerOrders() { $orders = $this->_orderCollectionFactory->create()->addFieldToSelect( '*' )->addFieldToFilter( 'customer_id', $this->getCurrentCustomerId() ); return $orders; } public function getCurrentProduct() { return $this->_registry->registry('current_product'); } public function isCurrentCustomerPurchasedThisProduct() { $product_ids = []; foreach ($this->getCustomerOrders() as $order) { foreach ($order->getAllVisibleItems() as $item) { $product_ids[$item->getProductId()] = $item->getProductId(); } } if (in_array($this->getCurrentProduct()->getId(), $product_ids)) { return true; } else { return false; } } }

 

3. Add your custom message when review form is not available to the customer if he/she has not purchased the product yet.

 

app/code/Vendor/Module/view/frontend/templates/no_review_form.phtml

 

You can not add the review on this product as you have not purchased this product yet.

 

 

If you find my answer useful, Please click Kudos & Accept as Solution.

View solution in original post

4 REPLIES 4

Re: Magento 2 - Product Reviews only by customer who purchased the product

Hello @Sandip Magento

 

You have to add the condition here.
If the current customer has purchased the current product, then load the review form otherwise show the custom message or don't load any template.

Follow the steps given below

 

1. Override the Review form block with your custom block

 

app/code/Vendor/Module/etc/di.xml

 

 

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
	<preference for="Magento\Review\Block\Form" type="Vendor\Module\Block\Review\Form" />
</config>

 

2. Add condition for the customer in your custom block

 

app/code/Vendor/Module/Block/Review/Form.php

 

 

<?php

namespace Vendor\Module\Block\Review;

class Form extends \Magento\Review\Block\Form
{
	/**
     * Customer Session Factory
     *
     * @var \Magento\Customer\Model\SessionFactory
     */
	protected $_customerSession;
	/**
     * Order Collection Factory
     *
     * @var \Magento\Sales\Model\ResourceModel\Order\CollectionFactory
     */
	protected $_orderCollectionFactory;
	/**
     * Registry
     *
     * @var \Magento\Framework\Registry
     */
	protected $_registry;
	/**
     * Review data
     *
     * @var \Magento\Review\Helper\Data
     */
    protected $_reviewData = null;

    /**
     * Catalog product model
     *
     * @var \Magento\Catalog\Api\ProductRepositoryInterface
     */
    protected $productRepository;

    /**
     * Rating model
     *
     * @var \Magento\Review\Model\RatingFactory
     */
    protected $_ratingFactory;

    /**
     * @var \Magento\Framework\Url\EncoderInterface
     */
    protected $urlEncoder;

    /**
     * Message manager interface
     *
     * @var \Magento\Framework\Message\ManagerInterface
     */
    protected $messageManager;

    /**
     * @var \Magento\Framework\App\Http\Context
     */
    protected $httpContext;

    /**
     * @var \Magento\Customer\Model\Url
     */
    protected $customerUrl;

    /**
     * @var array
     */
    protected $jsLayout;

    /**
     * @var \Magento\Framework\Serialize\Serializer\Json
     */
    private $serializer;

    /**
     * Form constructor.
     *
     * @param \Magento\Framework\View\Element\Template\Context $context
     * @param \Magento\Framework\Url\EncoderInterface $urlEncoder
     * @param \Magento\Review\Helper\Data $reviewData
     * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
     * @param \Magento\Review\Model\RatingFactory $ratingFactory
     * @param \Magento\Framework\Message\ManagerInterface $messageManager
     * @param \Magento\Framework\App\Http\Context $httpContext
     * @param Url $customerUrl
     * @param array $data
     * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
     * @throws \RuntimeException
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
	public function __construct(
		\Magento\Framework\View\Element\Template\Context $context,
        \Magento\Framework\Url\EncoderInterface $urlEncoder,
        \Magento\Review\Helper\Data $reviewData,
        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
        \Magento\Review\Model\RatingFactory $ratingFactory,
        \Magento\Framework\Message\ManagerInterface $messageManager,
        \Magento\Framework\App\Http\Context $httpContext,
        \Magento\Customer\Model\Url $customerUrl,
        array $data = [],
        \Magento\Framework\Serialize\Serializer\Json $serializer = null,
		\Magento\Customer\Model\SessionFactory $customerSession,
		\Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory,
		\Magento\Framework\Registry $registry
	) {
		$this->_customerSession = $customerSession;
		$this->_orderCollectionFactory = $orderCollectionFactory;
		$this->_registry = $registry;
		parent::__construct($context, $urlEncoder, $reviewData, $productRepository, $ratingFactory, $messageManager, $httpContext, $customerUrl, $data);
		$this->jsLayout = isset($data['jsLayout']) ? $data['jsLayout'] : [];
		$this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
            ->get(\Magento\Framework\Serialize\Serializer\Json::class);
	}
	
	protected function _construct()
	{
		parent::_construct();

		if ($this->isCurrentCustomerPurchasedThisProduct()) {
			$this->setTemplate('Magento_Review::form.phtml');
		} else {
$this->setTemplate('Vendor_Module::no_review_form.phtml');
// You can set null here if you don't want to load any template
// $this->setTemplate(null); } } public function getCurrentCustomerId() { return $this->_customerSession->create()->getCustomer()->getId(); } public function getCustomerOrders() { $orders = $this->_orderCollectionFactory->create()->addFieldToSelect( '*' )->addFieldToFilter( 'customer_id', $this->getCurrentCustomerId() ); return $orders; } public function getCurrentProduct() { return $this->_registry->registry('current_product'); } public function isCurrentCustomerPurchasedThisProduct() { $product_ids = []; foreach ($this->getCustomerOrders() as $order) { foreach ($order->getAllVisibleItems() as $item) { $product_ids[$item->getProductId()] = $item->getProductId(); } } if (in_array($this->getCurrentProduct()->getId(), $product_ids)) { return true; } else { return false; } } }

 

3. Add your custom message when review form is not available to the customer if he/she has not purchased the product yet.

 

app/code/Vendor/Module/view/frontend/templates/no_review_form.phtml

 

You can not add the review on this product as you have not purchased this product yet.

 

 

If you find my answer useful, Please click Kudos & Accept as Solution.

View solution in original post

Re: Magento 2 - Product Reviews only by customer who purchased the product

Thanks @Mayur Bhuva for your effort and answer.  Let me give a try.

Re: Magento 2 - Product Reviews only by customer who purchased the product

Bro @Mayur Bhuva 

 

Not really an answer but gotta say this!

Almost 2 years later that's still helpful, I'm using 2.3.5-p1 and still no option to do that or extensions that I found, saying this, create it on git under your name so it's easier to install and some other people can improve like activating or deactivating the text and change the text in admin, I think that would help some people, great job!

 

Best regards

Re: Magento 2 - Product Reviews only by customer who purchased the product

Hi,

 

I know this is an older post; I'm using Magento 2.4.3 and while the code works, I get an error displayed at the top of the product page on the front end.

 

"An error has happened during application run. See exception log for details."

 

Nothing is in the exception.log but the below is in the system.log

 

main.CRITICAL: Error: Call to a member function getId() on null in /app/code/Vendor/Module/Block/Review/Form.php:163

Line "163" in my Form.php is :

if (in_array($this->getCurrentProduct()->getId(), $product_ids)) {

 

I followed all the instructions from the solution except I added this as a module and had to include a module.xml file in /app/code/Vendor/Module/etc and registration.php in /app/code/Vendor/Module which is pretty standard.

 

Any advise would be greatly appreciated.