I created this module about a year ago. Maybe because of elasticseach
search engine or something now I am facing this error in Magento 2.4.1
main.CRITICAL: Error: Call to undefined method Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\Interceptor::getCollectionClone() in D:\xampp\htdocs\ms241\app\code[Vendor]\LayeredNavigation\Model\Layer\Filter\Attribute.php:115
The full function in the Attribute.php
file is like this
protected function _getItemsData()
{
if (!$this->_moduleHelper->isLayeredNavigationEnabled()) {
return parent::_getItemsData();
}
$attribute = $this->getAttributeModel();
/** @var \[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection $productCollection */
$productCollection = $this->getLayer()->getProductCollection();
if ($this->_isFilter) {
$productCollection = $productCollection->getCollectionClone()
->removeAttributeSearch($attribute->getAttributeCode());// ERROR HERE
}
$optionsFacetedData = $productCollection->getFacetedData($attribute->getAttributeCode());
if (count($optionsFacetedData) === 0
&& $this->getAttributeIsFilterable($attribute) !== static::ATTRIBUTE_OPTIONS_ONLY_WITH_RESULTS
) {
return $this->itemDataBuilder->build();
}
$productSize = $productCollection->getSize();
$itemData = [];
$checkCount = false;
$options = $attribute->getFrontend()
->getSelectOptions();
foreach ($options as $option) {
if (empty($option['value'])) {
continue;
}
$value = $option['value'];
$count = isset($optionsFacetedData[$value]['count'])
? (int)$optionsFacetedData[$value]['count']
: 0;
// Check filter type
if ($this->getAttributeIsFilterable($attribute) == static::ATTRIBUTE_OPTIONS_ONLY_WITH_RESULTS
&& (!$this->_moduleHelper->getFilterModel()->isOptionReducesResults($this, $count, $productSize))
) {
continue;
}
if ($count > 0) {
$checkCount = true;
}
$itemData[] = [
'label' => $this->tagFilter->filter($option['label']),
'value' => $value,
'count' => $count
];
}
if ($checkCount) {
foreach ($itemData as $item) {
$this->itemDataBuilder->addItemData($item['label'], $item['value'], $item['count']);
}
}
return $this->itemDataBuilder->build();
Module's di.xml
file is like this
<?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="categoryFilterList" type="Magento\Catalog\Model\Layer\FilterList">
<arguments>
<argument name="filters" xsi:type="array">
<item name="attribute" xsi:type="string">[Vendor]\LayeredNavigation\Model\Layer\Filter\Attribute</item>
<item name="price" xsi:type="string">[Vendor]\LayeredNavigation\Model\Layer\Filter\Price</item>
<item name="category" xsi:type="string">[Vendor]\LayeredNavigation\Model\Layer\Filter\Category</item>
</argument>
</arguments>
</virtualType>
<virtualType name="searchFilterList" type="Magento\Catalog\Model\Layer\FilterList">
<arguments>
<argument name="filters" xsi:type="array">
<item name="attribute" xsi:type="string">[Vendor]\LayeredNavigation\Model\Layer\Filter\Attribute</item>
<item name="price" xsi:type="string">[Vendor]\LayeredNavigation\Model\Layer\Filter\Price</item>
<item name="category" xsi:type="string">[Vendor]\LayeredNavigation\Model\Layer\Filter\Category</item>
</argument>
</arguments>
</virtualType>
<virtualType name="Magento\CatalogSearch\Model\ResourceModel\Fulltext\CollectionFactory" type="Magento\Catalog\Model\ResourceModel\Product\CollectionFactory">
<arguments>
<argument name="instanceName" xsi:type="string">[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection</argument>
</arguments>
</virtualType>
<virtualType name="Magento\CatalogSearch\Model\ResourceModel\Fulltext\SearchCollection" type="[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection">
<arguments>
<argument name="searchRequestName" xsi:type="string">quick_search_container</argument>
</arguments>
</virtualType>
</config>
If I do this change navigation filter won't show
if ($this->_isFilter) {
//$productCollection = $productCollection->getCollectionClone()
// ->removeAttributeSearch($attribute->getAttributeCode());
$productCollectionClone = clone $productCollection;
$productCollectionClone->removeAttributeSearch($attribute->getAttributeCode());
}
$optionsFacetedData = $productCollectionClone->getFacetedData($attribute->getAttributeCode()); // ERROR HERE
main.CRITICAL: Notice: Undefined variable: productCollectionClone in D:\xampp\htdocs\ms241\app\code[Vendor]\LayeredNavigation\Model\Layer\Filter\Attribute.php on line 121
And If I do this change navigation filter is showing but not working
if ($this->_isFilter) {
//$productCollection = $productCollection->getCollectionClone()
// ->removeAttributeSearch($attribute->getAttributeCode());
$productCollection = clone $productCollection;
$productCollection->removeAttributeSearch($attribute->getAttributeCode());
}
main.CRITICAL: Error: Call to undefined method Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\Interceptor::removeAttributeSearch() in D:\xampp\htdocs\ms241\app\code[Vendor]\LayeredNavigation\Model\Layer\Filter\Attribute.php:118
[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection.php
has getCollectionClone()
& removeAttributeSearch()
functions like this
public function getCollectionClone()
{
if ($this->collectionClone === null) {
$this->collectionClone = clone $this;
$this->collectionClone->setSearchCriteriaBuilder($this->searchCriteriaBuilder->cloneObject());
}
$searchCriterialBuilder = $this->collectionClone->getSearchCriteriaBuilder()->cloneObject();
/** @var \[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection $collectionClone */
$collectionClone = clone $this->collectionClone;
$collectionClone->setSearchCriteriaBuilder($searchCriterialBuilder);
return $collectionClone;
}
public function removeAttributeSearch($attributeCode)
{
if (is_array($attributeCode)) {
foreach ($attributeCode as $attCode) {
$this->searchCriteriaBuilder->removeFilter($attCode);
}
} else {
$this->searchCriteriaBuilder->removeFilter($attributeCode);
}
$this->_isFiltersRendered = false;
return $this->loadWithFilter();
}
After adding this to di.xml
<virtualType name="elasticsearchLayerCategoryItemCollectionProvider" type="Magento\Elasticsearch\Model\Layer\Category\ItemCollectionProvider">
<arguments>
<argument name="factories" xsi:type="array">
<item name="elasticsearch7" xsi:type="object">[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\CollectionFactory</item><!-- Alioze AdrienF -->
</argument>
</arguments>
</virtualType>
<virtualType name="elasticsearchLayerSearchItemCollectionProvider" type="Magento\Elasticsearch\Model\Layer\Search\ItemCollectionProvider">
<arguments>
<argument name="factories" xsi:type="array">
<item name="elasticsearch7" xsi:type="object">[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\CollectionFactory</item><!-- Alioze AdrienF -->
</argument>
</arguments>
</virtualType>
And changing this Magento\Elasticsearch\SearchAdapter\Query\Builder\Sort.php
private const DEFAULT_SKIPPED_FIELDS = [
'entity_id',
];
To
private const DEFAULT_SKIPPED_FIELDS = [
null,
'entity_id',
];
I am able to filter products with single filter value like one color or one size but multiple selection not working giving me this errors
{"0":"Sorry, something went wrong. You can find out more in the error log.","1":" #1 Magento\Framework\Data\Collection\AbstractDb->_renderFilters() called at [app\code\[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection.php:391]\n #2 [Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection->_renderFilters() called at [vendor\magento\framework\Data\Collection\AbstractDb.php:578]\n #3 Magento\Framework\Data\Collection\AbstractDb->loadWithFilter(false, false) called at [generated\code\[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection\Interceptor.php:1076]\n #4 [Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection\Interceptor->loadWithFilter() called at [app\code\[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection.php:179]\n #5 [Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection->removeAttributeSearch('color') called at [generated\code\[Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection\Interceptor.php:41]\n #6 [Vendor]\LayeredNavigation\Model\ResourceModel\Fulltext\Collection\Interceptor->removeAttributeSearch('color') called at [app\code\[Vendor]\LayeredNavigation\Model\Layer\Filter\Attribute.php:116]\n #7 [Vendor]\LayeredNavigation\Model\Layer\Filter\Attribute->_getItemsData() called at [vendor\magento\module-catalog\Model\Layer\Filter\AbstractFilter.php:202]\n #8 Magento\Catalog\Model\Layer\Filter\AbstractFilter->_initItems() called at [vendor\magento\module-catalog\Model\Layer\Filter\AbstractFilter.php:159]\n #9 Magento\Catalog\Model\Layer\Filter\AbstractFilter->getItems() called at [vendor\magento\module-catalog\Model\Layer\Filter\AbstractFilter.php:148]\n#10
Basically, the module was for multiple selections of navigation filters. Like we can choose filter color red and black or any other color also. The same goes for other filters.
I have checked this module is working in Magento 2.3.2 with PHP version 7.1.7 where Configuration->Catalog->Catalog Search->Search engine is = MYSQL
There are many files so let me know if anything else needs to be shared here. Any help would be great.