사용자 정의 페이지의 사용자 정의 콜렉션에 대한 계층 탐색-magento2


12

사용자 지정 제품 컬렉션을 위해 magento2에서 계층 탐색을 가져 오는 중입니다. 사용자 정의 페이지에 이미 사용자 정의 콜렉션이 표시되어 계층 탐색을 표시해야합니다. magento1 솔루션 을 조정하려고 시도 했지만 멀리 가지 못했습니다.

어떻게 magento2에서 그것을 달성 할 수 있습니까? 내가 지금까지 한 일은 다음과 같습니다.

내 사용자 정의 페이지에서 사용자 정의 제품 목록에 대한 Catalog ListProduct 블록을 확장했습니다.

class View extends \Magento\Catalog\Block\Product\ListProduct
{


    public function __construct(
    \Magento\Catalog\Block\Product\Context $context,
    \Magento\Framework\Data\Helper\PostHelper $postDataHelper,
    \Magento\Catalog\Model\Layer\Resolver $layerResolver,
    CategoryRepositoryInterface $categoryRepository,
    \Magento\Framework\Url\Helper\Data $urlHelper,
    array $data = [],
    \Custom\LayerNavigation\Model\Layer $testlayerobj
    ) {
        parent::__construct($context,$postDataHelper,$layerResolver,
        $categoryRepository,$urlHelper,$data);
        $this->_coreRegistry = $context->getRegistry();
        $this->_testlayer = $testlayerobj;
    }

    protected function _getProductCollection()
    {
        if ($this->_productCollection === null) {
          $this->_productCollection = $this->getLayer()->getProductCollection();
        }
        return $this->_productCollection;
     }

    public function getLayer()
    {

       $layer = $this->_coreRegistry->registry('current_layer');
       if ($layer) {
          return $layer;
        }
        return $this->_testlayer;
     }

}

레이아웃 파일에서 계층 탐색에 핵심 검색 블록을 사용했습니다.

<referenceContainer name="sidebar.main">
        <block class="Magento\LayeredNavigation\Block\Navigation\Search" name="catalogsearch.leftnav" before="-" template="layer/view.phtml">
            <block class="Magento\LayeredNavigation\Block\Navigation\State" name="catalogsearch.navigation.state" as="state" />
            <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="catalogsearch.navigation.renderer" as="renderer" template="layer/filter.phtml"/>
        </block>
</referenceContainer>

컬렉션을 수정하기위한 확장 코어 레이어 모델.

class Layer extends \Magento\Catalog\Model\Layer
{
    public function __construct(
      optionStoreFactory  $optionstoreFactory,
      Attrhelper $attrhelper,
      productCollectionFactory $productCollectionFactory,
      AttributevalueFactory $attributevalueFactory,
      CategoryRepositoryInterface $categoryRepository,
      \Magento\Store\Model\StoreManagerInterface $storeManager,
      \Magento\Framework\App\Request\Http $request,
      \Magento\Framework\Registry $registry,
      \Magento\Catalog\Model\Layer\Search\CollectionFilter $filter,
      array $data = []
    ) {
       $this->optionstoreFactory       = $optionstoreFactory;
       $this->attributevalueFactory    = $attributevalueFactory;
       $this->_attrhelper              = $attrhelper;
       $this->request                  = $request;
       $this->productCollectionFactory = $productCollectionFactory;
       $this->categoryRepository = $categoryRepository;
       $this->_storeManager = $storeManager;
       $this->filter = $filter;
       $this->registry = $registry;
    }

    public function getProductCollection()
    {
        $attributevalue = $this->getAttributeValue(); //eg: Manufacturer Attribute details
        $attr_code = $attributevalue->getAttributeCode();
        $attr_option_value = $attributevalue->getOptionId();
        $collection = $this->productCollectionFactory->create();
        $store_id = $this->request->getParam('store_id');
        $collection->addAttributeToSelect('*')
               ->addAttributeToFilter($attr_code , ['finset'=>$attr_option_value ])
               ->addAttributeToFilter('visibility','4')
               ->setStore($store_id)
               ->addFieldToFilter('status', array('eq' => 1))
               ->setOrder('id', 'DESC');
        $this->prepareProductCollection($collection);
        return $collection;
    }

    public function prepareProductCollection($collection)
    {
        $this->filter->filter($collection, $this->getCurrentCategory());
       return $this;
    }

    public function getCurrentCategory()
    {
       $category = $this->registry->registry('current_category');
       if ($category) {
           $this->setData('current_category', $category);
       } else {
           $category = $this->categoryRepository->get($this->getCurrentStore()->getRootCategoryId());
       $this->setData('current_category', $category);
       }
      return $category;
    }

    public function getCurrentStore()
    {
        return $this->_storeManager->getStore();
    }

}

현재 레이어 탐색이 표시되지만 내 사용자 지정 컬렉션과 관련이 없습니다. 내 디버깅에 따라 컬렉션은 루트 범주 (전체 제품 카탈로그가 포함되어 있음)에서 완전히 필터링되며 그에 따라 레이어를 가져옵니다.


어떤 제안이라도 대단히 감사하겠습니다 ..!
mp196

그것에 대한 해결책을 찾았습니까? 그렇다면 답변을 공유하십시오
Nalin Savaliya

여러분들 중 누구라도 이것에 대해 어떤 단서를 가지고 있습니까?
aton1004

내 사용자 지정 컬렉션에 대한 사용자 지정 페이지에서 계층화 된 탐색을 얻는 데 성공했습니다. 솔루션이 매우 길기 때문에 여기에 솔루션을 게시하는 데 약간의 시간이 필요합니다 (아마 하루나 이틀 안에 솔루션을 게시 할 예정 임)
mp196

답변:


3

아래 변경 사항으로 탐색을 수행 할 수 있었 으므로이 솔루션으로 완전히 정확하지 않을 수 있으므로 의견과 제안을 가장 환영합니다.

1) 다음과 같이 프론트 엔드 섹션에 di.xml을 준비하십시오.

<!-- Magento only includes 2 type of layer resolvers i.e Category and search whereas our custom page is neither a category page nor a search page so we need to add a new layer resolver on our custom page-->
<type name="Magento\Catalog\Model\Layer\Resolver">
    <arguments>
        <argument name="layersPool" xsi:type="array">
            <item name="category" xsi:type="string">Magento\Catalog\Model\Layer\Category</item>
            <item name="search" xsi:type="string">Magento\Catalog\Model\Layer\Search</item>
            <item name="customlayer" xsi:type="string">Custom\Navigation\Model\Layer</item>
        </argument>
    </arguments>
</type>

<!-- To prepare the filterlist for our custom collection which would be passed to the left navigation we need below virtual types for our custom page navigation -->
<virtualType name="customFilterList" type="Custom\Navigation\Model\Layer\FilterList">
    <arguments>
        <argument name="filterableAttributes" xsi:type="object">Custom\Navigation\Model\Layer\FilterableAttributeList</argument>
        <argument name="filters" xsi:type="array">
            <item name="attribute" xsi:type="string">Custom\Navigation\Model\Layer\Filter\Attribute</item>
            <item name="category" xsi:type="string">Custom\Navigation\Model\Layer\Filter\Category</item>
        </argument>
    </arguments>
</virtualType>

<!-- once the filter list virtual type is ready we can pass the same to our navigation , I have prepared the virtual type of the core navigation for my custom module and have passed the custom filter list to it -->
<virtualType name="Custom\Navigation\Block\Navigation\Custnavigation" type="Magento\LayeredNavigation\Block\Navigation">
    <arguments>
        <argument name="filterList" xsi:type="object">customFilterList</argument>
    </arguments>
</virtualType>

<!-- As we will be modifying the layer model collection we will need to extend the core model layer, Below virtual type will be required to extend the Catalog model layer else it will throw error for the context in construct method-->
<virtualType name="Custom\Navigation\Model\Layer\Context" type="Magento\Catalog\Model\Layer\Context">
    <arguments>
        <argument name="collectionProvider" xsi:type="object">Custom\Navigation\Model\Layer\ItemCollectionProvider</argument>
        <argument name="stateKey" xsi:type="object">Custom\Navigation\Model\Layer\StateKey</argument>
        <argument name="collectionFilter" xsi:type="object">Custom\Navigation\Model\Layer\CollectionFilter</argument>
    </arguments>
</virtualType>
<type name="Custom\Navigation\Model\Layer">
    <arguments>
        <argument name="context" xsi:type="object">Custom\Navigation\Model\Layer\Context</argument>
    </arguments>
</type>

2) 모델 레이어 파일 : 사용자 정의 모델로 모델 레이어 파일을 확장하고 컬렉션을 수정합니다.

namespace Custom\Navigation\Model;
class Layer extends \Magento\Catalog\Model\Layer
{

//Apart from the default construct argument you need to add your model from which your product collection is fetched.

    public function __construct(
        \Magento\Catalog\Model\Layer\ContextInterface $context,
        \Magento\Catalog\Model\Layer\StateFactory $layerStateFactory,
        AttributeCollectionFactory $attributeCollectionFactory,
        \Magento\Catalog\Model\ResourceModel\Product $catalogProduct,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Registry $registry,
        CategoryRepositoryInterface $categoryRepository,
        array $data = []
    ) {
    parent::__construct(
            $context,
            $layerStateFactory,
            $attributeCollectionFactory,
            $catalogProduct,
            $storeManager,
            $registry,
            $categoryRepository,
            $data
        );
    }

    public function getProductCollection()
    {

        /*Unique id is needed so that when product is loaded /filtered in the custom listing page it will be set in the
         $this->_productCollections array with unique key else you will not get the updated or proper collection.
        */

        if (isset($this->_productCollections['some_uinique_id'])) {
            $collection = $this->_productCollections['some_uinique_id'];
        } else {
            //$collection = Your logic to get your custom collection.
            $this->prepareProductCollection($collection);
            $this->_productCollections['some_unique_id'] = $collection;
        }

        return $collection;
    }

3) di.xml에 사용 된 파일 아래로 확장했습니다 (필요한 경우 확장 파일에서 특정 기능을 수정할 수있는 경우이 파일의 변경이 필요하지 않으므로 생성 방법으로 인스턴스화하지 않았으므로 파일을 그대로 유지했습니다) 따라서), 현재 내가 적용 한 솔루션은 여전히 ​​카테고리 필터 문제를 해결할 수 없었지만 여전히 루트 카테고리 필터를 포함하므로 패싯 데이터를 포함하는 해결 방법을 수행해야했습니다 (4 번째 지점에서 언급 한 해결 방법)

- Custom\Navigation\Model\Layer\FilterList extends
           \Magento\Catalog\Model\Layer\FilterList



 - Custom\Navigation\Model\Layer\FilterableAttributeList extends
   \Magento\Catalog\Model\Layer\Category\FilterableAttributeList



 - Custom\Navigation\Model\Layer\Filter\Attribute extends
   \Magento\Catalog\Model\Layer\Filter\Attribute



 - Custom\Navigation\Model\Layer\Filter\Category extends
   \Magento\CatalogSearch\Model\Layer\Filter\Category (Why catalog
           search is used i have mentioned the same in 4th point)



 - Custom\Navigation\Model\Layer\ItemCollectionProvider extends
   \Magento\Catalog\Model\Layer\Category\ItemCollectionProvider



 - Custom\Navigation\Model\Layer\StateKey extends
   \Magento\Catalog\Model\Layer\Category\StateKey



 - Custom\Navigation\Model\Layer\CollectionFilter extends
   \Magento\Catalog\Model\Layer\Category\CollectionFilter

4) 필터링 된 컬렉션에 대한 옵션을 표시하지 않았기 때문에 계층 탐색에서 범주 필터에 대한 해결 방법을 수행해야합니다. 솔루션을 찾은 경우 업데이트를 수행하십시오. 아래는 내 customfilterlist에 카테고리를 포함하는 동안 직면 한 faceteddata 오류를 수정하는 데 사용한 코드입니다.이 패치를 적용하기 때문에 내 탐색에 카테고리 옵션이 표시되지 않았습니다. 나머지 필터는 내 컬렉션에 따라 적절했습니다.

namespace Custom\Navigation\Model\Layer\Filter;

/**
 * Layer category filter
 */
class Category extends \Magento\CatalogSearch\Model\Layer\Filter\Category
{
     /**
      * @var \Magento\Framework\Escaper
      */
    private $escaper;

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

    /**
     * @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\Catalog\Model\CategoryFactory $categoryFactory
     * @param \Magento\Framework\Escaper $escaper
     * @param CategoryManagerFactory $categoryManager
     * @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\Catalog\Model\Layer\Filter\DataProvider\CategoryFactory $categoryDataProviderFactory,
        array $data = []
    ) {
        parent::__construct(
            $filterItemFactory,
            $storeManager,
            $layer,
            $itemDataBuilder,
            $escaper,
            $categoryDataProviderFactory,
            $data
        );
        $this->_escaper = $escaper;
        $this->_requestVar = 'cat';
        $this->dataProvider = $categoryDataProviderFactory->create(['layer' => $this->getLayer()]);
    }

    /**
     * Get data array for building category filter items
     *
     * @return array
     */
    protected function _getItemsData()
    {
        /** @var \Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection $productCollection */
        $productCollection = $this->getLayer()->getProductCollection();

        $optionsFacetedData = '' ;// $productCollection->getFacetedData('category'); (Here i have set $optionsFacetedData as blank so that category option will not be included in layered navigation)
        $category = $this->dataProvider->getCategory();
        $categories = $category->getChildrenCategories();

        $collectionSize = $productCollection->getSize();

        if ($category->getIsActive()) {
            foreach ($categories as $category) {
                if ($category->getIsActive()
                    && isset($optionsFacetedData[$category->getId()])
                    && $this->isOptionReducesResults($optionsFacetedData[$category->getId()]['count'], $collectionSize)
                ) {
                    $this->itemDataBuilder->addItemData(
                        $this->escaper->escapeHtml($category->getName()),
                        $category->getId(),
                        $optionsFacetedData[$category->getId()]['count']
                    );
                }
            }
        }
        return $this->itemDataBuilder->build();
    }
}

5) 커스텀 페이지가 컨트롤러 실행 메소드에로드되면 di.xml에 추가 한 커스텀 레이어를 카테고리 및 검색 레이어와 함께 설정해야합니다.

 - include the below argument in your controller construct method.

     "\Magento\Catalog\Model\Layer\Resolver $layerResolver",

 - inside execute method set your custom layer resolver for your module.

    $this->layerResolver->create('customlayer');

6) 사용자 정의 페이지의 레이아웃 xml 파일에서 본문 섹션에 아래 코드를 추가하십시오.

<attribute name="class" value="page-with-filter"/>

<referenceContainer name="sidebar.main">
<!-- below is the virtual type of the core navigation we created -->
    <block class="Custom\Navigation\Block\Navigation\Custnavigation" name="custom.leftnav" before="-" template="Magento_LayeredNavigation::layer/view.phtml">
        <block class="Magento\LayeredNavigation\Block\Navigation\State" name="catalog.navigation.state" as="state" />
        <block class="Magento\LayeredNavigation\Block\Navigation\FilterRenderer" name="catalog.navigation.renderer" as="renderer" template="Magento_LayeredNavigation::layer/filter.phtml"/>
    </block>
</referenceContainer>

magento 2.1.7에서 사용자 정의 컬렉션으로 코드를 사용하고 있습니다. 하지만 빈 페이지가 나타납니다. 위 코드에서 Custom \ Navigation \ Block \ Navigation \ Custnavigation이 누락되었다고 생각합니다. 전체 코드를 알려주시겠습니까?
Magecode

아니 대신 가상 블록을 만든 그런 블록이 없습니다 .di.xml 코드를 확인할 수 있으며 여기에 게시 된 코드는 전체 코드 자체입니다.
mp196

좋아, 전체 코드를 우편으로 보내 주시겠습니까?
마법사 코드

위의 답변 코드는 개발 한 유료 확장 프로그램의 일부일 뿐이므로 우편을 보낼 수 없습니다.
mp196

1
$ this-> layerResolver = $ layerResolver를 추가했는지 확인하십시오; 파일 생성자에 추가 된 클래스의 구문에서 \ Magento \ Catalog \ Model \ Layer \ Resolver $ layerResolver
mp196

2

카테고리 페이지의 계층 탐색 및 도구 모음에 사용자 정의 제품 콜렉션을 성공적으로 적용했습니다.

예를 들어 가격이 100 미만인 제품 컬렉션을 가져오고 있습니다.

1 단계 : 아래 코드 스 니펫 추가

앱 / 코드 / 공급 업체 / 모듈 /etc/di.xml

<?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="Magento\Catalog\Model\Layer">
        <plugin name="custom_product_model_layer" type="Vendor\Module\Plugin\Layer" />
    </type>

    <type name="Magento\Catalog\Block\Product\ProductList\Toolbar">
        <plugin name="custom_product_toolbar" type="Vendor\Module\Plugin\Toolbar" />
    </type>

    <virtualType name="categoryFilterList" type="Magento\Catalog\Model\Layer\FilterList">
        <arguments>
            <argument name="filters" xsi:type="array">
                <item name="attribute" xsi:type="string">Magento\Catalog\Model\Layer\Filter\Attribute</item>
                <item name="price" xsi:type="string">Magento\Catalog\Model\Layer\Filter\Price</item>
                <item name="decimal" xsi:type="string">Magento\Catalog\Model\Layer\Filter\Decimal</item>
                <item name="category" xsi:type="string">Magento\Catalog\Model\Layer\Filter\Category</item>
            </argument>
        </arguments>
    </virtualType>

</config>

2 단계 : 제품 콜렉션 용 플러그인 작성

앱 / 코드 / 공급 업체 / 모듈 / 플러그인 /Layer.php

<?php
namespace Vendor\Module\Plugin;
class Layer
{
  public function aroundGetProductCollection(
    \Magento\Catalog\Model\Layer $subject,
    \Closure $proceed
  ) {

    $result = $proceed();
    $result->addAttributeToFilter('price', array('lt' => 100));
    return $result;
  }
}

3 단계 : 툴바 용 플러그인 만들기

앱 / 코드 / 공급 업체 / 모듈 / 플러그인 /Toolbar.php

<?php
namespace Vendor\Module\Plugin;
class Toolbar
{

  protected $_objectManager;
  protected $request;

  public function __construct(
    \Magento\Framework\ObjectManagerInterface $objectmanager,
    \Magento\Framework\App\Request\Http $request
  ) {
    $this->_objectManager = $objectmanager;
    $this->request = $request;
  }

  public function aroundSetCollection(
    \Magento\Catalog\Block\Product\ProductList\Toolbar $subject,
    \Closure $proceed,
    $request
  ) {
    $result = $proceed($request);

    $this->_collection = $request;
    $category = $this->_objectManager->get('Magento\Framework\Registry')->registry('current_category');
    if($category)
    {
      $page = $this->request->getParam('p');
      if($page == '')
      {
        $page = 1;
      }
      $this->_collection->getCurPage();
      $this->_collection->setCurPage($page);  
    }
    //else
    //{
    //  $this->_collection->setCurPage($this->getCurrentPage());
    //}

    return $result;
  }

}

안녕하세요, 코드를 사용하여 제품 컬렉션 상관 관계를 업데이트했지만 범주, 가격, 속성 및 제품 수와 같은 FIlterList를 업데이트하지 않습니다. 이걸 도와 줄 수 있니? @DineshYadav
Sujeet Pandit

귀하의 솔루션은 완벽하게 작동했습니다. 특정 범주를 듣고 컬렉션을 완전히 다시 작성하기 위해 종과 휘파람을 추가했습니다.
pixiemedia

@pixiemedia 당신은 그것이 당신을 위해 일한 경우 내 대답을 upvote 수 있습니다 ☺️
Dinesh Yadav

플러그인 코드에서 마지막 부분 이후의 마지막 부분은 검색 결과를 깰 수 있습니다. 그 비트 아웃 의견
pixiemedia

M2.2에 대한 작업이 중지되었습니다-SQL 오류 SQLSTATE [42S22] : 열을 찾을 수 없음 : 1054 'field list'에서 알 수없는 열 'e.min_price'– 솔루션 작업
pixiemedia

0

사용자 지정 페이지의 사용자 지정 제품 컬렉션에서 주로 작동하는 계층 탐색을 얻을 수있었습니다. 모듈에 대한 소스 코드를 여기에 업로드했습니다 . 유일한 문제는 가격 필터가 올바른 제품 수를 표시하지 않는다는 것입니다. 이로 인해 가격 필터를 숨기도록 계층 탐색 뷰를 수정했습니다. 그러나 사용자 정의보기 파일을 사용했기 때문에 어떤 이유로 사이드 바의 필터를 더 이상 축소 할 수 없습니다.

누구든지 그 문제를 해결할 수 있다면 언제든지 풀 요청을하십시오. 또한 xml을 통해 수동으로 생성 된 페이지 대신 Magento 2 백엔드를 통해 생성 된 CMS 페이지에이를 구현하는 방법을 알아 내려고 노력 중입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.