Is there any way by custom code or plugin, products can be hide from entire frontend shop based on custom attribute type yes or no ?
3 Answers
The Magento standard way would be to use the visibility attribute but if you have to do it with a custom attribute here's something that'll get you started, and may be all you need.
There isn't one function that can overridden to completely control product visibility but this is a good way to control the visibility of products on category pages.
etc/frontend/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\Model\Layer\Category\CollectionFilter">
<plugin name="vendorname_modulename_catalog_model_layer_category_collectionfilter" type="VendorName\ModuleName\Plugin\CollectionFilter"/>
</type>
</config>
Plugin/CollectionFilter.php
<?php
namespace VendorName\ModuleName\Plugin;
class CollectionFilter
{
public function afterFilter(
\Magento\Catalog\Model\Layer\Category\CollectionFilter $subject,
$result,
\Magento\CatalogSearch\Model\ResourceModel\FullText\Collection $collection,
\Magento\Catalog\Model\Category $category
) {
$collection->addAttributeToFilter('custom_attribute', 'custom_value');
}
}
After fixing error about the above solution, I could find the solution.
The proper solution is as follow.
etc/frontend/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\Model\Layer\Category\CollectionFilter">
<plugin name="vendorname_modulename_catalog_model_layer_category_collectionfilter" type="Vendorname\Modulename\Plugin\CollectionFilter"/>
</type>
app/code/Vendorname/Modulename/Plugin/CollectionFilter
namespace Vendorname\Modulename\Plugin;
class CollectionFilter
{
public function afterFilter(
\Magento\Catalog\Model\Layer\Category\CollectionFilter $subject,
$result,
\Magento\Catalog\Model\ResourceModel\Product\Collection $collection,
\Magento\Catalog\Model\Category $category
) {
$collection->addAttributeToFilter('custom_attribute', $custom_value);
}
}
The plugin's parameters must be $subject, $result and same parameters of Magento\Catalog\Model\Layer\Category\CollectionFilter's filter().
we can find it on vendor\magento\module-catalog\Model\Layer\Category\CollectionFilter.php
/**
* Filter product collection
*
* @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection
* @param \Magento\Catalog\Model\Category $category
* @return void
*/
public function filter(
$collection,
\Magento\Catalog\Model\Category $category
) {
$collection
->addAttributeToSelect($this->catalogConfig->getProductAttributes())
->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->addUrlRewrite($category->getId())
->setVisibility($this->productVisibility->getVisibleInCatalogIds());
}
That's why the 3rd parameter must be as follow.
\Magento\Catalog\Model\ResourceModel\Product\Collection $collection
The above method works, but it results in the page navigation being off.
For example, if you are viewing 12 items per page with a total of 24 results, and hide one item on the first page, the first page should show a total of 12. With this change, there will only be 11 items on the first page.