Magento 2: Як гранітні дані працюють для багатошарової навігації?


10

Я створив модуль для спеціального фільтра на сторінці категорій, все працює нормально, за винятком цінового діапазону в багатошаровій навігації.

Будь-хто може пояснити мені, як getFacetedData ("ціна") працює в magento2

$productCollection->getFacetedData('price');

Ця функція дає мені діапазони цін на основі колекції товарів за замовчуванням, а не на основі моєї відфільтрованої колекції.

FYI: Я відфільтрував колекцію, як показано нижче,

$productCollection = $layer->getProductCollection()
->clear()
->addAttributeToSelect(['name','price'])
->addAttributeToFilter('sku', array('in' => ['sku1','sku2']));

Відповіді:


7

Код нижче застосовується до Magento 2.2.5.

Спочатку на бічній панелі потрібно створити всі можливі діапазони для всіх можливих фільтрів. Крім того, до цього ви матимете огляд кількості продуктів, знайдених у межах даного асортименту.

введіть тут опис зображення

Наприклад, я зупинюсь на використанні одного фільтра: ціна.

Перш за все, для того, щоб даний атрибут продукту мав право на багатошарову навігацію, його слід правильно налаштувати.

Щоб перевірити, перегляньте в адміністраторі до Stores -> Attribute -> Product, а потім виберіть атрибут ціни та дотримуйтесь того, що на Storefront Propertiesвкладці Use in Layered Navigationвстановлено значенняFilterable (with results)

На цій фотографії ми бачимо, що для фільтра цін ми бачимо діапазон від 50.00-59.99містить 10результати, і 80+лише для них 1.

Цей погляд виробляється всередині

/vendor/magento/theme-frontend-luma/Magento_LayeredNavigation/templates/layer/view.phtml

Існує код, подібний до

<?php foreach ($block->getFilters() as $filter): ?>
    <?php if ($filter->getItemsCount()): ?>

Що в підсумку складеться до

private function prepareData($key, $count)

і це метод від

vendor/magento/module-catalog-search/Model/Layer/Filter/Price.php

Отже, ми визначили клас, який відповідає за фільтрацію цін, і ми бачимо, що він вже використовувався для створення доступних діапазонів.


Більш важливий стек - це перевірити, що відбувається при виборі певного діапазону.

Наприклад, я натисну діапазон 40,00-49,99, який, як очікується, поверне 4 результати.

Спочатку - метод _prepareLayout()від

/vendor/magento/module-layered-navigation/Block/Navigation.php

Код є

protected function _prepareLayout()
{
    foreach ($this->filterList->getFilters($this->_catalogLayer) as $filter) {
        $filter->apply($this->getRequest());
    }
    $this->getLayer()->apply();
    return parent::_prepareLayout();
}

По суті, це говорить, заведіть мені всі фільтри і пророкуйте їх apply.

Тепер само getFilters () призводить до побудови об'єкта з

vendor/magento/module-catalog-search/Model/Layer/Filter/Price.php

Зухвалий крок , який веде до __constructз PriceIS

protected function createAttributeFilter(
    \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute,
    \Magento\Catalog\Model\Layer $layer
) {
    $filterClassName = $this->getAttributeFilterClass($attribute);

    $filter = $this->objectManager->create(
        $filterClassName,
        ['data' => ['attribute_model' => $attribute], 'layer' => $layer]
    );
    return $filter;
}

І це код від

vendor/module-catalog/Model/Layer/FilterList.php

У будь-якому випадку, якщо ми звернемося до $filter->apply($this->getRequest());коду зверху, це означає, що цей код буде виконаний

public function apply(\Magento\Framework\App\RequestInterface $request)
{
    /**
     * Filter must be string: $fromPrice-$toPrice
     */
    $filter = $request->getParam($this->getRequestVar());
    if (!$filter || is_array($filter)) {
        return $this;
    }

    $filterParams = explode(',', $filter);
    $filter = $this->dataProvider->validateFilter($filterParams[0]);
    if (!$filter) {
        return $this;
    }

    $this->dataProvider->setInterval($filter);
    $priorFilters = $this->dataProvider->getPriorFilters($filterParams);
    if ($priorFilters) {
        $this->dataProvider->setPriorIntervals($priorFilters);
    }

    list($from, $to) = $filter;

    $this->getLayer()->getProductCollection()->addFieldToFilter(
        'price',
        ['from' => $from, 'to' =>  empty($to) || $from == $to ? $to : $to - self::PRICE_DELTA]
    );

    $this->getLayer()->getState()->addFilter(
        $this->_createItem($this->_renderRangeLabel(empty($from) ? 0 : $from, $to), $filter)
    );

    return $this;
}

і знову цей код від

vendor/magento/module-catalog-search/Model/Layer/Filter/Price.php

Якщо я уважно слідкую за змінними значеннями, знову ж таки, враховуючи, що я вибрав діапазон 40,00-49,99, то $filterмасив складається з двох елементів: [0 => 40, 1 => 50]

Після виконання цього рядка

list($from, $to) = $filter;

Очевидно, що $fromзмінна зараз 40, а $toзмінна зараз 50.

Наступний рядок має вирішальне значення

    $this->getLayer()->getProductCollection()->addFieldToFilter(
        'price',
        ['from' => $from, 'to' =>  empty($to) || $from == $to ? $to : $to - self::PRICE_DELTA]
    );

Тут вже зменшується вже наявна колекція, пов'язана з шаром, викликом addFieldToFilter().

Можливо, саме тут слід звернути увагу на виявлення помилок, якщо такі є.

Зрештою, програма викликає getLoadedProductCollection () з

vendor/magento/module-catalog/Block/Product/ListProduct.php

який у efect повертає захищену колекцію, яку цей об'єкт інкапсулює.


Magento - це складне застосування.

У цьому одному клацанні миші, який вибрав один єдиний діапазон цін, ми побачили код із трьох різних модулів, що взаємодіють

  • модуль-каталог
  • модуль-каталог-пошук
  • модульно-багатошарова навігація

Можливо, це може здатися непосильним на моменти, але мені здається, приємна синергія між цими модулями.

Дякую за прочитане Я сподіваюся, що це пояснює, і ви зараз оснащені трохи кращим розумінням шаруватої навігації.


+1 за дуже детальну та добре пояснену відповідь. Однак ви не пояснили, як працюють гранітні дані ... Фацетні дані використовуються для генерування кількості фільтрів.
Йонн Триморо

привіт @Marjan, у моєму випадку категорія третього рівня не відображається у фільтрі, ось моє запитання, magento.stackexchange.com/questions/270442/…
jafar pinjar
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.