Magento 2: Jak działają dane aspektowe w nawigacji warstwowej?

10

Stworzyłem moduł niestandardowego filtra na stronie kategorii, wszystko działa dobrze oprócz przedziału cenowego w nawigacji warstwowej.

Proszę, ktoś może mi wyjaśnić, jak działa getFacetedData („cena”) w magento2

$productCollection->getFacetedData('price');

Ta funkcja daje mi przedziały cenowe w oparciu o domyślną kolekcję produktów, a nie na podstawie mojej filtrowanej kolekcji.

FYI: Przefiltrowałem kolekcję jak poniżej,

$productCollection = $layer->getProductCollection()
->clear()
->addAttributeToSelect(['name','price'])
->addAttributeToFilter('sku', array('in' => ['sku1','sku2']));
Nalin Savaliya
źródło

Odpowiedzi:

7

Poniższy kod dotyczy Magento 2.2.5.

Po pierwsze, na pasku bocznym należy wygenerować wszystkie możliwe zakresy dla wszystkich możliwych filtrów. Dodatkowo będziesz miał przegląd liczby produktów znalezionych w danym zakresie.

wprowadź opis zdjęcia tutaj

Na przykład skupię się na użyciu jednego filtra: ceny.

Przede wszystkim, aby dany atrybut produktu kwalifikował się do nawigacji warstwowej, należy go odpowiednio skonfigurować.

Aby to sprawdzić, przejdź do administratora Stores -> Attribute -> Product, a następnie wybierz atrybut ceny i zauważ, że na Storefront Propertieskarcie Use in Layered Navigationustawiono wartośćFilterable (with results)

Na tym zdjęciu widzimy, że dla filtra cen widzimy zakres od 50.00-59.99zawiera 10wyniki i 80+tylko dla 1.

Ten widok jest produkowany w środku

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

Istnieje kod podobny do

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

Który ostatecznie się kumuluje

private function prepareData($key, $count)

i to jest metoda z

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

Zidentyfikowaliśmy więc klasę odpowiedzialną za filtrowanie cen i widzimy, że została już wykorzystana do wytworzenia dostępnych zakresów.


Ważniejszym stosem jest sprawdzenie, co się stanie, gdy zostanie wybrany określony zakres.

Na przykład kliknę na zakres 40,00-49,99, który powinien dać 4 wyniki.

Najpierw jest metoda _prepareLayout()od

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

Kod jest

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

W gruncie rzeczy, mówi to, weź mi wszystkie filtry i wymień je apply.

Teraz sama metoda getFilters () ostatecznie prowadzi do konstruowania obiektu z

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

Powołanie krok, który prowadzi do __constructod 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;
}

A to jest kod z

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

W każdym razie, jeśli skupimy się ponownie na $filter->apply($this->getRequest());powyższym kodzie, oznacza to, że ten kod zostanie wykonany

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;
}

i znowu ten kod pochodzi z

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

Jeśli ponownie śledzę wartości zmiennych, biorąc pod uwagę, że wybrałem zakres 40,00–49,99, $filterto tablica składa się z dwóch elementów: [0 => 40, 1 => 50]

Po wykonaniu tej linii

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

Oczywiście $fromzmienna ma teraz 40, a $tozmienna ma teraz 50.

Kolejna linia jest kluczowa

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

W tym miejscu już obecna kolekcja związana z warstwą zostaje jeszcze bardziej zmniejszona przez wywołanie addFieldToFilter().

Być może w tym miejscu należy zwrócić uwagę na ewentualne błędy.

Ostatecznie program wywołuje getLoadedProductCollection () z

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

która w efekcie zwraca chronioną kolekcję, którą ten obiekt hermetyzuje.


Magento to złożona aplikacja.

W tym jednym kliknięciu, które wybrało jeden przedział cen, zobaczyliśmy kod z trzech różnych modułów współpracujących

  • modułowy katalog
  • przeszukiwanie katalogu modułów
  • modułowa nawigacja

W niektórych momentach może się przytłaczać, ale wydaje mi się, że między tymi modułami jest miła synergia.

Dziękuję za przeczytanie. Mam nadzieję, że to wyjaśnia i jesteś teraz wyposażony w nieco lepsze zrozumienie nawigacji warstwowej.

Marjan
źródło
+1 za bardzo szczegółową i ładnie wyjaśnioną odpowiedź. Jednak nie wyjaśniłeś, jak działają dane fasetowane ... Dane fasetowe są używane do generowania liczby filtrów.
Yonn Trimoreau,
cześć @Marjan, w moim przypadku kategoria trzeciego poziomu nie wyświetla się w filtrze, oto moje pytanie, magento.stackexchange.com/questions/270442/...
jafar pinjar