Elasticsuite: Count products in virtual category

Created on 3 Apr 2017  路  8Comments  路  Source: Smile-SA/elasticsuite

Is it possible to fetch the number of products matching the virtual category? I mean fo fetch (maybe collection or simple count products) if I have an instance of virtual category?

Preconditions

OS: Linux debian-8 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1+deb8u2 (2017-03-07) x86_64 GNU/Linux
Magento Version: 2.1.4 CE
ElasticSuite Version: 2.3.3
Environment: developer

Most helpful comment

You are right, the factory is a virtual type and cannot therefore being injected directly.

You should have this :

block :

class Test extends \Magento\Framework\View\Element\Template
{
    private $catalogLayer;

    private $collectionFactory;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Magento\Catalog\Model\Layer\Resolver $layerResolver,
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory,
        array $data
    ) {

        $this->collectionFactory = $collectionFactory;
        $this->catalogLayer = $layerResolver->get();
        parent::__construct($context, $data);
    }

    protected function _prepareLayout()
    {
        $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/rorua.log');
        $logger = new \Zend\Log\Logger();
        $logger->addWriter($writer);

        $category   = $this->catalogLayer->getCurrentCategory(); // Or anyway else to retrieve a category.
        $collection = $this->collectionFactory->create();

        if ($category->getIsVirtualCategory() && $category->getVirtualRule()) {
            $queryFilter = $category->getVirtualRule()->getCategorySearchQuery($category);
            $collection->addQueryFilter($queryFilter);
        } else {
            $collection->addCategoryFilter($category);
        }

        $count = $collection->getSize();
        $logger->info(" Count : " . $count);

        return parent::_prepareLayout();
    }
}

di :

<?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="\MyCodePool\Catalog\Block\Test">
        <arguments>
            <argument name="collectionFactory" xsi:type="object">Magento\CatalogSearch\Model\ResourceModel\Fulltext\CollectionFactory</argument>
        </arguments>
    </type>
</config>

All 8 comments

You can use Magento\Catalog\Model\Layer\Resolver :

        $layer = $this->layerResolver->get();
        $count = $layer->setCurrentCategory($category)->getProductCollection()->getSize();  

@romainruaud, no, it's not working. It shows me 195 for each category when it's only six products in category.

Hmm you are right,

please try with Magento\CatalogSearch\Model\ResourceModel\Fulltext\CollectionFactory :

        $collection = $this->collectionFactory()->create();
        if ($category->getIsVirtualCategory() && $category->getVirtualRule()) {
            $queryFilter = $category->getVirtualRule()->getCategorySearchQuery($category);
            $collection->addQueryFilter($queryFilter);
        } else {
            $collection->addCategoryFilter($category);  
        }
        $count = $collection->getSize();  

Hmmm... I've got the next error:

Fatal error: Uncaught TypeError: Argument 3 passed to XXX\WidgetSubcategoryList\Block\Widget\Subcategories::__construct() must be an instance of Magento\CatalogSearch\Model\ResourceModel\Fulltext\CollectionFactory, instance of Magento\Catalog\Model\ResourceModel\Product\CollectionFactory given, called in /home/www/xxx/www/xxx.dev/vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php on line 93 and defined in /home/www/xxx/www/xxx.dev/app/code/XXX/WidgetSubcategoryList/Block/Widget/Subcategories.php on line 41

I've checked the instance and deleted the var folder. But it still appears.

You are right, the factory is a virtual type and cannot therefore being injected directly.

You should have this :

block :

class Test extends \Magento\Framework\View\Element\Template
{
    private $catalogLayer;

    private $collectionFactory;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Magento\Catalog\Model\Layer\Resolver $layerResolver,
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $collectionFactory,
        array $data
    ) {

        $this->collectionFactory = $collectionFactory;
        $this->catalogLayer = $layerResolver->get();
        parent::__construct($context, $data);
    }

    protected function _prepareLayout()
    {
        $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/rorua.log');
        $logger = new \Zend\Log\Logger();
        $logger->addWriter($writer);

        $category   = $this->catalogLayer->getCurrentCategory(); // Or anyway else to retrieve a category.
        $collection = $this->collectionFactory->create();

        if ($category->getIsVirtualCategory() && $category->getVirtualRule()) {
            $queryFilter = $category->getVirtualRule()->getCategorySearchQuery($category);
            $collection->addQueryFilter($queryFilter);
        } else {
            $collection->addCategoryFilter($category);
        }

        $count = $collection->getSize();
        $logger->info(" Count : " . $count);

        return parent::_prepareLayout();
    }
}

di :

<?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="\MyCodePool\Catalog\Block\Test">
        <arguments>
            <argument name="collectionFactory" xsi:type="object">Magento\CatalogSearch\Model\ResourceModel\Fulltext\CollectionFactory</argument>
        </arguments>
    </type>
</config>

@romainruaud now it works! Thank you so much!

@romainruaud hello!
I know this is an old post but I have the same issue and I'm using Magento 2.2.3
I followed your instructions but I get this error:

PHP Fatal error: Uncaught Error: Call to undefined method Magento\Catalog\Model\ResourceModel\Product\Collection\Interceptor::addQueryFilter() in /.../app/code/Vendor/Module/Block/VirtualCategories.php:78

Do you have any suggestion?

Thank you!

@romainruaud your code is working correctly only it not work when we call this from category_save after event catalog_category_save_after it returns the error No such entity with id = 0

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wintermute-84 picture wintermute-84  路  4Comments

rvitaliy picture rvitaliy  路  3Comments

tschirmer picture tschirmer  路  4Comments

sdasun picture sdasun  路  4Comments

lingwooc picture lingwooc  路  5Comments