Код ниже относится к 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();
}
По сути, это говорит о том, чтобы получить все фильтры и foreach из них сделать apply
.
Теперь только getFilters () в конечном итоге приводит к созданию объекта из
vendor/magento/module-catalog-search/Model/Layer/Filter/Price.php
Вызывающий шаг , который ведет к __construct
из Price
IS
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]
);
Это где уже существующая коллекция, связанная с Layer, дополнительно сокращается путем вызова addFieldToFilter()
.
Возможно, именно на это следует обратить внимание, чтобы обнаружить ошибки, если они есть.
В конце концов, программа вызывает getLoadedProductCollection () из
vendor/magento/module-catalog/Block/Product/ListProduct.php
который в efect возвращает защищенную коллекцию, которую этот объект инкапсулирует.
Magento - сложное приложение.
В этом единственном щелчке, который выбрал один единственный диапазон цен, мы увидели код из трех разных модулей, взаимодействующих
- модуль-каталог
- модуль-каталог-поиск
- модуль-слоисто-навигация
Временами это может показаться ошеломляющим, но мне кажется, что между этими модулями есть хорошая синергия.
Спасибо за чтение. Я надеюсь, что это объясняет, и вы теперь немного лучше разбираетесь в многоуровневой навигации.