Die Paginierung des benutzerdefinierten Bewertungsfilters für die Magento 2-Ebenen-Navigation funktioniert nicht

8

Ich habe ein Modul für den Bewertungsfilter und seine Funktionsweise erstellt, aber nach der Filternummer des Elements und der Paginierung wird gemäß dem beigefügten Screenshot eine falsche Anzeige angezeigt.

Es gibt nur ein 5-Start-Produkt, das jedoch einen falschen Artikel und eine falsche Paginierung aufweist.

Unten ist der Code, der von mir entwickelt wurde:

app/code/Namespace/Catalog/Model/Layer/Filter/Rating.php

<?php

/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Namespace\Catalog\Model\Layer\Filter;

use Magento\Catalog\Model\Category as CategoryModel;
use Magento\Catalog\Model\CategoryFactory as CategoryModelFactory;
use Magento\Catalog\Model\Layer;
use Magento\Framework\Registry;

/**
 * Layer category filter
 *
 * @author      Magento Core Team <[email protected]>
 */
class Rating extends \Magento\Catalog\Model\Layer\Filter\AbstractFilter {

    /**
     * Active Category Id
     *
     * @var int
     */
    protected $_categoryId;

    /**
     * Applied Category
     *
     * @var \Magento\Catalog\Model\Category
     */
    protected $_appliedCategory;

    /**
     * Core data
     *
     * @var \Magento\Framework\Escaper
     */
    protected $_escaper;

    /**
     * Core registry
     *
     * @var \Magento\Framework\Registry
     */
    protected $_coreRegistry;

    /**
     * @var CategoryDataProvider
     */
    private $dataProvider;

    /**
     * Construct
     *
     * @param \Magento\Catalog\Model\Layer\Filter\ItemFactory $filterItemFactory
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Catalog\Model\Layer $layer
     * @param \Magento\Catalog\Model\Layer\Filter\Item\DataBuilder $itemDataBuilder
     * @param \Magento\Framework\Escaper $escaper
     * @param CategoryFactory $categoryDataProviderFactory
     * @param array $data
     */
    public function __construct(
    \Magento\Catalog\Model\Layer\Filter\ItemFactory $filterItemFactory,
    \Magento\Store\Model\StoreManagerInterface $storeManager, 
    \Magento\Catalog\Model\Layer $layer, 
    \Magento\Catalog\Model\Layer\Filter\Item\DataBuilder $itemDataBuilder, 
    \Magento\Framework\Escaper $escaper, 
    \Magento\Framework\ObjectManagerInterface $objectManager, 
    \Magento\Catalog\Model\Product $productModel, 
    \Magento\Catalog\Model\Product\Attribute\Source\Status $productStatus, 
    \Magento\Catalog\Model\Product\Visibility $productVisibility, 
    \Magento\Store\Model\StoreManagerInterface $storeManager,            
    array $data = []
    ) {
         $this->_storeManager = $storeManager;        
        parent::__construct($filterItemFactory, $storeManager, $layer, $itemDataBuilder, $data);
        $this->_escaper = $escaper;
        $this->objectManager = $objectManager;
        $this->_productModel = $productModel;
        $this->productStatus = $productStatus;
        $this->productVisibility = $productVisibility;
         $this->_requestVar = 'rating';
    }

    protected $stars = array(
        1 => 20,
        2 => 40,
        3 => 60,
        4 => 80,
        5 => 100,
    );    

    /**
     * Get filter value for reset current filter state
     *
     * @return mixed|null
     */


    /**
     * Apply category filter to layer
     *
     * @param   \Magento\Framework\App\RequestInterface $request
     * @return  $this
     */
    public function apply(\Magento\Framework\App\RequestInterface $request) {
        /**
         * Filter must be string: $fromPrice-$toPrice
         */
        $filter = $request->getParam($this->getRequestVar());
        if (!$filter) {
            return $this;
        }
        $collection = $this->getLayer()->getProductCollection();
        $select = $collection->getSelect();
        $minRating = (array_key_exists($filter, $this->stars))
            ? $this->stars[$filter]
            : 0;
        $reviewSummary = 'review_entity_summary';
        $select->joinLeft(
            array('rating' => $reviewSummary),
            sprintf('`rating`.`entity_pk_value`=`e`.entity_id
                    AND `rating`.`entity_type` = 1
                    AND `rating`.`store_id`  =  %d',
                $this->_storeManager->getStore()->getId()
            ),
            ''
        );
        $select->where('`rating`.`rating_summary` >= ?',
            $minRating);
        $state = $this->_createItem($this->getLabelHtml($filter), $filter)
                      ->setVar($this->_requestVar);
        $this->getLayer()->getState()->addFilter($state);


        return $this;
    }

    /**
     * Get filter name
     *
     * @return \Magento\Framework\Phrase
     */
    public function getName() {
        return __('Rating');
    }

    protected function _getItemsData()
    {   
        $data = array();
        $count = $this->_getCount();

        $currentValue = $this->getRequestVar();
        for ($i=1;$i<=5;$i++) {
            $data[] = array(
                'label' => $this->getLabelHtml($i),
                'value' => ($currentValue == $i) ? null : $i,
                'count' => $count[($i-1)],
                'option_id' => $i,
            );
        }
        return $data;
    }
    /**
     * @return array
     */
    protected function _getCount()
    {
        $collection = $this->getLayer()->getProductCollection();
        $connection = $collection->getConnection();
        $connection
            ->query('SET @ONE :=0, @TWO := 0, @THREE := 0, @FOUR := 0, @FIVE := 0');
        $select = clone $collection->getSelect();

        $select->reset(\Zend_Db_Select::COLUMNS);
        $select->reset(\Zend_Db_Select::ORDER);
        $select->reset(\Zend_Db_Select::LIMIT_COUNT);
        $select->reset(\Zend_Db_Select::LIMIT_OFFSET);
        $select->reset(\Zend_Db_Select::WHERE);      
        $reviewSummary = 'review_entity_summary';
        $select->joinLeft(
            array('rsc' => $reviewSummary),
            sprintf('`rsc`.`entity_pk_value`=`e`.entity_id
                AND `rsc`.entity_type = 1
                AND `rsc`.store_id  =  %d',
                $this->_storeManager->getStore()->getId()),
            'rsc.rating_summary AS rating'
        );
        $columns = new \Zend_Db_Expr("
            IF(`rsc`.`rating_summary` <  40, @ONE := @ONE + 1, 0),
            IF(`rsc`.`rating_summary` >= 40 AND `rsc`.`rating_summary` < 60, @TWO := @TWO + 1, 0),
            IF(`rsc`.`rating_summary` >= 60 AND `rsc`.`rating_summary` < 80, @THREE := @THREE + 1, 0),
            IF(`rsc`.`rating_summary` >= 80 AND `rsc`.`rating_summary` < 100, @FOUR := @FOUR + 1, 0),
            IF(`rsc`.`rating_summary` >= 100, @FIVE := @FIVE + 1, 0)
        ");
        $select->columns($columns);
        $connection->query($select);
        $result = $connection->fetchRow('SELECT @ONE, @TWO, @THREE, @FOUR, @FIVE;');
        return array_values($result);
    }
    protected function _initItems()
    {   
        $data  = $this->_getItemsData();

        $items = array();
        foreach ($data as $itemData) {
            $item = $this->_createItem(
                $itemData['label'],
                $itemData['value'],
                $itemData['count']
            );
            $item->setOptionId($itemData['option_id']);
            $items[] = $item;
        }
        $this->_items = $items;

        return $this;
    }

    protected function getLabelHtml($countStars)
    {
         $html = '<div class="rating-summary" style="display: inline-block;margin-top: -5px;">
                                        <div class="rating-result" title="100%">
                                            <span style="width:'.$countStars*20 .'%"></span>
                                        </div>
                                    </div>';
        return $html;
    }



}

?>

Geben Sie hier die Bildbeschreibung ein

Nikunj Vadariya
quelle
Hallo Nikunj Vadariya, hast du eine Antwort auf diese Frage gefunden?
Ruud N.
Was passiert nur aus Neugier, wenn Sie die zweite Seite besuchen?
Juhanix
@juhanix es wird gesagt, dass Produkte, die der Auswahl entsprechen, nicht gefunden werden können.
Ruud N.

Antworten:

1

Was das Problem für mich behoben hat, war unglaublich einfach und doch so schwer zu finden: $collection->getSize();

Sie müssen diese Methode in der Apply-Methode Ihres Filters aufrufen.

EDIT: mein Arbeitscode unten

public function apply(\Magento\Framework\App\RequestInterface $request)
    {
        $filter = $request->getParam($this->getRequestVar(), null);
        if (is_null($filter)) {
            return $this;
        }
        $this->_activeFilter = true;

        $collection = $this->getLayer()->getProductCollection();
        $collection->setFlag(self::WIDTH_COLLECTION_FLAG, true);

        // Paste magic code to calculate $included_entities, which is an array of product id's. 

        $collection->getSelect()->where('e.entity_id IN (' . implode(',',$included_entities) . ')');
        $this->getLayer()->getState()->addFilter(
            $this->_createItem($filter, $filter)
        );
        $collection->getSize(); // This did the trick!
        return $this;
    }
Ruud N.
quelle
Bitte teilen Sie
Ihren Arbeitscode,
Die Antwort wurde entsprechend aktualisiert.
Ruud N.
@ NikunjVadariya Ich brauche Hilfe zum Filtern von Kumpel
Sarvesh Dineshkumar Patel
0

Kannst du es stattdessen versuchen?

$collection = $this->getLayer()->getProductCollection();

zu

$collection = $this->getLayer()->getLoadedProductCollection();

Ich stand vor ähnlichen Problemen und wurde dadurch gelöst.

Kaushal Suthar
quelle
Vielen Dank für Ihre Antwort, aber getLoadedProductCollection ist keine Methode in \ Magento \ Catalog \ Model \ Layer.
Ruud N.