Skip to content

Review observer does load() on collection, which causes issues for other observers. #11910

Closed
@Floddy

Description

@Floddy

Preconditions

  1. Install Magento 2.2 via composer

Steps to reproduce

  1. Create a module that hooks into the event catalog_block_product_list_collection
  2. The module should have the sequence so it's ran after Magento_Review
  3. Use addAttributeToSelect to add a product attribute to the collection in the observer

Alternatively:

  1. Use the addAttribute method inside the Magento\Catalog\Block\Product\ListProduct block to add a product attribute to the collection

Expected result

  1. The product attribute is included in the collection

Actual result

  1. The product attribute is not included in the collection

Cause and solution

The cause of this is because:
Magento\Review\Observer\CatalogBlockProductCollectionBeforeToHtmlObserver.php uses the catalog_block_product_list_collection event, and does a $collection->load in the observer, which makes it not possible to use addAttributeToSelect afterwards.

Magento\Review should IMO instead use a plugin, that runs 'after' Magento\Catalog\Block\Product\ListProduct, which does the same thing as the observer - because what the functionality really needs to do, is to add the review data to the loaded collection:

<type name="Magento\Catalog\Block\Product\ListProduct">
    <plugin name="reviewCollectionInitializer" type="Magento\Review\Block\Product\ListProduct\Plugin\Review" />
</type>
<?php

namespace Magento\Review\Block\Product\ListProduct\Plugin;

class Review
{
    protected $_reviewFactory;
    
    public function __construct(
        \Magento\Review\Model\ReviewFactory $reviewFactory
    ) { 
        $this->_reviewFactory = $reviewFactory;
    }   
    
    public function afterGetLoadedProductCollection($subject, $result)
    {
        $productCollection = $result;
        if ($productCollection instanceof \Magento\Framework\Data\Collection) {
            $this->_reviewFactory->create()->appendSummary($productCollection);
        }   
        return $productCollection;
    }   
}   

There seems to be a similar plugin for the product compare list block, so I'm not sure why this isn't implemented in a similar way?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions