Your code found in the issue that was reported to Magento github: https://github.com/magento/magento2/issues/34502
Firstly, I'm not sure that code resolves the sorting product by position issue.
Now, let's back to your question: how to override Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection to fix the sort by position issue on the category page?
Override Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection is quite complex and different from other classes. Due to the issue only affected on the category page we have to override elasticsearchCategoryCollection which override Magento\CatalogSearch\Model\ResourceModel\Fulltext\CollectionFactory
To do this, take the following steps:
Step 1: Create registration.php:
- File path: app/code/Jan/CatalogSearch/registration.php
- Content:
<?php
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Jan_CatalogSearch', DIR);
Step 2: Create module.xml:
- File path: app/code/Jan/CatalogSearch/etc/module.xml
- Content:
<?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="Jan_CatalogSearch">
<sequence>
<module name="Magento_CatalogSearch"/>
<module name="Magento_Elasticsearch"/>
</sequence>
</module>
</config>
Step 3: Create di.xml:
- File path: app/code/Jan/CatalogSearch/etc/di.xml
- Content:
<?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="Jan\CatalogSearch\Model\ResourceModel\Fulltext\Collection"/>
</config>
Step 4: Create Model\ResourceModel\Fulltext\Collection file.
- File path: app/code/Jan/CatalogSearch/Model/ResourceModel/Fulltext/Collection.php
- Content:
<?php
namespace Jan\CatalogSearch\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\Framework\EntityManager\MetadataPool;
use Magento\Framework\Api\Search\SearchResultFactory;
use Magento\Catalog\Model\ResourceModel\Product\Collection\ProductLimitationFactory;
/**
- Fulltext Collection
- Customize to fix sort by position does not work in magento 2.4
- This collection should be refactored to not have dependencies on MySQL-specific implementation.
- @api
- @since 100.0.2
- @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- @SuppressWarnings(PHPMD.TooManyFields)
- @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
/
class Collection extends \Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection
{
/*
* @var \Magento\Framework\App\RequestInterface
*/
private $request;
/**
* @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 \Magento\Framework\App\RequestInterface $request
* @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,
\Magento\Framework\App\RequestInterface $request,
$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->request = $request;
$this->searchRequestName = $searchRequestName;
}
/**
* @inheritdoc
*/
protected function _renderFiltersBefore()
{
if ($this->searchRequestName === 'catalog_view_container') {
$attribute = $this->request->getParam("product_list_order", "position");
$direction = $this->request->getParam("product_list_dir", "asc");
$this->addAttributeToSort($attribute, $direction);
}
parent::_renderFiltersBefore();
}
}
Step 5: Run setup upgrade command to install and enable the module: bin/magento setup:upgrade
Step 6: Run compilation code command: bin/magento setup:di:compile
Step 7: Run deploy static content command: bin/magento setup:static-content:deploy -f
You are done.
====
Explaination more about the change to your code: You code has some issues:
elasticsearchCategoryCollectionget from Magento_Elasticsearch which I added intosequencein module.xml – Tu Van Oct 18 '22 at 14:04if ($this->isLoaded()) {, then remove generated folder and re compile code. JUST DO IT in your locally, don't do it in production. – Tu Van Oct 25 '22 at 15:10