0

im trying to create an observer to only show products if the price is greater than 0, this is my code, I'm using it for this event "catalog_block_product_list_collection"

<?php

namespace Vendor\Module\Observer;

use Magento\Framework\Event\ObserverInterface;

class HideProductsNoPrice implements ObserverInterface
    {
        public function execute(\Magento\Framework\Event\Observer $observer)
        {    
            $collection = $observer->getData('collection');
            $collection->addAttributeToFilter('price',['gt'=>0]);
            return $this;
        }
    }

In my events.xml I have the following

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="catalog_block_product_list_collection">
        <observer name="hide_products_no_price" instance="Vendor\Module\Observer\HideProductsNoPrice" />
    </event>
</config>

Yet when I list the products I still see all of them, even if their price is 0.00. Am I missing something else? or am I using the wrong event to list the products? Any help would be really appreciated.

2 Answers 2

1

If you want modify the return or params of a function of Magento, is recommendable use the plugin instead of observer.

https://devdocs.magento.com/guides/v2.2/extension-dev-guide/plugins.html

If you want change the results in the catalog product list, you must do the next.

Vendor/Namespace/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">
<type name="Magento\Catalog\Block\Product\ListProduct">
    <plugin name="vendor_namespace_plugin_list" type="Vendor\Namespace\Plugin\ListProductPlugin"/>
</type>

Vendor/Namespace/Plugin/ListProductPlugin.php

<?php

namespace Vendor\Namespace\Plugin;

use Magento\Catalog\Block\Product\ListProduct;
use Magento\Eav\Model\Entity\Collection\AbstractCollection;
use Magento\Framework\Exception\LocalizedException;

/**
 * Class ListProductPlugin
 */
class ListProductPlugin
{

    /**
     * @param ListProduct $subject
     * @param AbstractCollection $resultCollection
     * @return AbstractCollection
     * @throws LocalizedException
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function afterGetLoadedProductCollection(
        ListProduct $subject,
        AbstractCollection $resultCollection
    ) {
        $resultCollection->addAttributeToSelect('price');
        $resultCollection->addAttributeToFilter('price', ['gt' => 0]);

        return $resultCollection;
    }
}

You must pay attention with the attribute price or final_price.

After read your comment, that you use the widgets catalog product list and catalog new product list, I recommend this.

For the widget catalog product list, the better way is use the conditions in the configuration of the widget. Attach screenshot. enter image description here

But, you prefer do it programmatically, you can do this.

Vendor/Namespace/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">
<type name="Magento\CatalogWidget\Block\Product\ProductsList">
     <plugin name="vendor_namespace_plugin_widget_list" type="Vendor\Namespace\Plugin\Widget\ProductListPlugin"/>
</type>

Vendor/Namespace/Plugin/Widget/ProductListPlugin.php

<?php

namespace Vendor\Namespace\Plugin\Widget;

use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\CatalogWidget\Block\Product\ProductsList;

/**
 * Class ProductListPlugin
 */
class ProductListPlugin
{

    /**
     * @param ProductsList $subject
     * @param Collection $resultCollection
     * @return Collection
     */
    public function afterCreateCollection(
        ProductsList $subject,
        Collection $resultCollection
    ) {
        $resultCollection->addAttributeToFilter('price', ['gt' => 0]);

        return $resultCollection;
    }
}

I have reviewed the widget new product list and I have not saw nothing for doing with a plugin, because its methods are protected or privated. I have thought that you can use as condition the attribute new and you only show the products which contains the value "yes". It's similar to screenshot attached with the example "price".

8
  • Can you explain me why is the plugin better? Does it have to do with performance or better Magento 2 programming practices? I've used plugins for other things and I really thought for this specific case an observer was more suitable. Thanks in advance Jun 24, 2018 at 23:20
  • "With events, there are always multiple objects in play when running the code: The original object generating the event, the event object, the observer object and the EventManager. With a plugin, there is actually one object in the end: The compiled interceptor object. This makes plugins more performant." by yireo.com/blog/1875-magent-2-observer-or-plugin .Also You can see this link devdocs.magento.com/guides/v2.2/coding-standards/…
    – raumatbel
    Jun 25, 2018 at 9:29
  • Hi, I just implemented the plugin as you suggested, but the products with price 0 are still showing, btw I'm displaying the products via a widget that I placed in the page, should I display the products via a different way? thanks Jun 25, 2018 at 13:39
  • Can you say me the widget code added in the page? May be that the block is different
    – raumatbel
    Jun 25, 2018 at 14:55
  • Hi I'm using 2 widgets, the 1st widget type I'm using is "Catalog Product List", and the 2nd widget type is "Catalog New Products List" and both of them, are showing the product with price $0.00 Jun 25, 2018 at 18:34
0

You filter the collection, but do not pass it on. Try this.

public function execute(\Magento\Framework\Event\Observer $observer)
        {    
            $collection = $observer->getData('collection');
            $gtZero = $collection->addAttributeToFilter('price',['gt'=>0]);
            $observer->setData('collection',$gtZero);
            // or $observer->setCollection($gtZero);
            return $this;
        }

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.