Since Magento 2.4 uses Elasticsearch,
- to show only configurable products on the product listing page (category page) you need to override
elasticsearchCategoryCollection
virtualType
which overrides Magento\CatalogSearch\Model\ResourceModel\Fulltext\CollectionFactory
- to show only configurable products on the search result page you need to override
elasticsearchFulltextSearchCollection
virtualType
which overrides Magento\CatalogSearch\Model\ResourceModel\Fulltext\SearchCollectionFactory
To achieve this, take the following steps:
Assume the Vendor name is TuVan
and the module name is Catalog
.
Step 1: Create registration.php:
File path: app/code/TuVan/Catalog/registration.php
<?php
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'TuVan_Catalog', __DIR__);
Step 2: Create module.xml:
File path: app/code/TuVan/Catalog/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="TuVan_Catalog">
<sequence>
<module name="Magento_CatalogSearch"/>
<module name="Magento_Elasticsearch"/>
</sequence>
</module>
</config>
Step 3: Create di.xml:
File path: app/code/TuVan/Catalog/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">
<virtualType name="elasticsearchCategoryCollection" type="TuVan\Catalog\Model\ResourceModel\Fulltext\Collection"/>
<virtualType name="elasticsearchFulltextSearchCollection" type="TuVan\Catalog\Model\ResourceModel\Fulltext\Collection"/>
</config>
Step 4: Create Model\ResourceModel\Fulltext\Collection class.
File path: app/code/TuVan/Catalog/Model/ResourceModel/Fulltext/Collection.php
<?php
namespace TuVan\Catalog\Model\ResourceModel\Fulltext;
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\DefaultFilterStrategyApplyCheckerInterface;
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\TotalRecordsResolverFactory;
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchCriteriaResolverFactory;
use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultApplierFactory;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\Api\Search\SearchResultFactory;
use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory;
/**
*
*
* Override to show only configurable products on product listing page and search result page
*
*/
class Collection extends \Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection
{
/**
* @var string
*/
private string $searchRequestName;
/**
* @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
* @param \Magento\Framework\Event\ManagerInterface $eventManager
* @param \Magento\Eav\Model\Config $eavConfig
* @param \Magento\Framework\App\ResourceConnection $resource
* @param \Magento\Eav\Model\EntityFactory $eavEntityFactory
* @param \Magento\Catalog\Model\ResourceModel\Helper $resourceHelper
* @param \Magento\Framework\Validator\UniversalFactory $universalFactory
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Framework\Module\Manager $moduleManager
* @param \Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
* @param \Magento\Catalog\Model\Product\OptionFactory $productOptionFactory
* @param \Magento\Catalog\Model\ResourceModel\Url $catalogUrl
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
* @param \Magento\Customer\Model\Session $customerSession
* @param \Magento\Framework\Stdlib\DateTime $dateTime
* @param \Magento\Customer\Api\GroupManagementInterface $groupManagement
* @param mixed $catalogSearchData
* @param mixed $requestBuilder
* @param mixed $searchEngine
* @param mixed $temporaryStorageFactory
* @param \Magento\Framework\DB\Adapter\AdapterInterface|null $connection
* @param string $searchRequestName
* @param SearchResultFactory|null $searchResultFactory
* @param ProductLimitationFactory|null $productLimitationFactory
* @param MetadataPool|null $metadataPool
* @param \Magento\Search\Api\SearchInterface|null $search
* @param \Magento\Framework\Api\Search\SearchCriteriaBuilder|null $searchCriteriaBuilder
* @param \Magento\Framework\Api\FilterBuilder|null $filterBuilder
* @param SearchCriteriaResolverFactory|null $searchCriteriaResolverFactory
* @param SearchResultApplierFactory|null $searchResultApplierFactory
* @param TotalRecordsResolverFactory|null $totalRecordsResolverFactory
* @param DefaultFilterStrategyApplyCheckerInterface|null $defaultFilterStrategyApplyChecker
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function __construct(
\Magento\Framework\Data\Collection\EntityFactory $entityFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
\Magento\Framework\Event\ManagerInterface $eventManager,
\Magento\Eav\Model\Config $eavConfig,
\Magento\Framework\App\ResourceConnection $resource,
\Magento\Eav\Model\EntityFactory $eavEntityFactory,
\Magento\Catalog\Model\ResourceModel\Helper $resourceHelper,
\Magento\Framework\Validator\UniversalFactory $universalFactory,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\Module\Manager $moduleManager,
\Magento\Catalog\Model\Indexer\Product\Flat\State $catalogProductFlatState,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Catalog\Model\Product\OptionFactory $productOptionFactory,
\Magento\Catalog\Model\ResourceModel\Url $catalogUrl,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\Customer\Model\Session $customerSession,
\Magento\Framework\Stdlib\DateTime $dateTime,
\Magento\Customer\Api\GroupManagementInterface $groupManagement,
$catalogSearchData = null,
$requestBuilder = null,
$searchEngine = null,
$temporaryStorageFactory = null,
\Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
$searchRequestName = 'catalog_view_container',
SearchResultFactory $searchResultFactory = null,
ProductLimitationFactory $productLimitationFactory = null,
MetadataPool $metadataPool = null,
\Magento\Search\Api\SearchInterface $search = null,
\Magento\Framework\Api\Search\SearchCriteriaBuilder $searchCriteriaBuilder = null,
\Magento\Framework\Api\FilterBuilder $filterBuilder = null,
SearchCriteriaResolverFactory $searchCriteriaResolverFactory = null,
SearchResultApplierFactory $searchResultApplierFactory = null,
TotalRecordsResolverFactory $totalRecordsResolverFactory = null,
DefaultFilterStrategyApplyCheckerInterface $defaultFilterStrategyApplyChecker = null
) {
parent::__construct(
$entityFactory,
$logger,
$fetchStrategy,
$eventManager,
$eavConfig,
$resource,
$eavEntityFactory,
$resourceHelper,
$universalFactory,
$storeManager,
$moduleManager,
$catalogProductFlatState,
$scopeConfig,
$productOptionFactory,
$catalogUrl,
$localeDate,
$customerSession,
$dateTime,
$groupManagement,
$catalogSearchData,
$requestBuilder,
$searchEngine,
$temporaryStorageFactory,
$connection,
$searchRequestName,
$searchResultFactory,
$productLimitationFactory,
$metadataPool,
$search,
$searchCriteriaBuilder,
$filterBuilder,
$searchCriteriaResolverFactory,
$searchResultApplierFactory,
$totalRecordsResolverFactory,
$defaultFilterStrategyApplyChecker
);
$this->searchRequestName = $searchRequestName;
}
/**
* @inheritdoc
*
* Override to show only configurable products on product listing page and search result page
*/
protected function _renderFiltersBefore()
{
$applyCustomFilterToSearchRequests = ['catalog_view_container', 'quick_search_container'];
if (in_array($this->searchRequestName, $applyCustomFilterToSearchRequests)) {
$this->addAttributeToFilter('type_id', Configurable::TYPE_CODE);
}
parent::_renderFiltersBefore();
}
}
Step 5: Install the module: bin/magento setup:upgrade
Step 6: Compile code: bin/magento setup:di:compile
Step 7: Deploy static content: bin/magento setup:static-content:deploy -f
You are done.