Navigasi berlapis untuk koleksi khusus pada halaman khusus - magento2

12

Saya sedang mengerjakan mengambil navigasi berlapis di magento2 untuk koleksi produk khusus. Saya sudah mendapatkan koleksi khusus di halaman kustom perlu menunjukkan navigasi berlapis. Mencoba mengadaptasi solusi magento1 ini tetapi tidak bisa jauh.

Ada ide bagaimana saya bisa mencapainya di magento2. Apa yang telah saya lakukan sejauh ini adalah sebagai berikut:

Memperpanjang blok Katalog Daftar Produk untuk daftar produk khusus pada halaman kustom saya.

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

}

Digunakan blok Pencarian inti untuk navigasi berlapis dalam file tata letak

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

Model lapisan Core Diperpanjang untuk memodifikasi koleksi.

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

}

Sampai sekarang saya mendapatkan navigasi layer yang ditampilkan tetapi tidak spesifik untuk koleksi khusus saya. Sesuai debug saya, koleksi disaring sepanjang jalan dari kategori root (Yang berisi katalog seluruh produk) dan menurut itu mengambil lapisan.

mp196
sumber
Setiap saran akan sangat dihargai ..!
mp196
Apakah Anda menemukan solusi untuk itu? Jika demikian, silakan bagikan jawaban Anda
Nalin Savaliya
Apakah ada yang punya petunjuk tentang ini ??
aton1004
Saya berhasil mendapatkan navigasi berlapis pada halaman kustom untuk koleksi kustom saya ... Akan memerlukan waktu untuk memposting solusi di sini karena sangat lama (Mungkin dalam satu atau dua hari saya akan memposting solusi)
mp196

Jawaban:

3

Saya dapat mencapai navigasi dengan perubahan di bawah ini, saya mungkin tidak sepenuhnya benar dengan solusi ini sehingga komentar dan saran dipersilahkan.

1) Siapkan di.xml untuk bagian frontend seperti di bawah ini:

<!-- 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) File Model Layer: Perpanjang file model layer dengan model kustom Anda dan modifikasi koleksi.

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) Saya telah memperluas file di bawah ini seperti yang digunakan dalam di.xml (Membuat file dengan hanya memperpanjang belum instantiated metode konstruksi karena saya tidak memerlukan perubahan dalam file ini jika diperlukan Anda dapat memodifikasi fungsi spesifik dalam file yang diperluas sesuai), Saat ini solusi yang saya terapkan tidak dapat menyelesaikan masalah filter kategori itu masih termasuk filter kategori root sehingga harus melakukan solusi untuk memasukkan faceteddata (solusi yang disebutkan dalam poin 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) Harus melakukan solusi untuk filter kategori dalam navigasi berlapis karena tidak menunjukkan opsi sehubungan dengan koleksi yang difilter, Jika ada yang menemukan solusinya, silakan lakukan pembaruan. Di bawah ini adalah kode yang saya gunakan untuk memperbaiki kesalahan faceteddata yang dihadapi saat memasukkan kategori di customfilterlist saya, Karena menerapkan tambalan ini, opsi kategori tidak ditampilkan di navigasi saya, sisa filter sesuai dengan koleksi saya.

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) Ketika halaman kustom Anda dimuat di dalam metode eksekusi controller Anda, Anda perlu mengatur lapisan kustom Anda yang kami tambahkan di di.xml bersama dengan kategori dan lapisan pencarian.

 - 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) Dalam file xml layout Anda untuk halaman kustom tambahkan kode di bawah ini di bagian tubuh.

<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>
mp196
sumber
Saya menggunakan kode Anda dengan koleksi khusus di magento 2.1.7. tetapi saya mendapatkan halaman kosong. Saya pikir Custom \ Navigation \ Block \ Navigation \ Custnavigation tidak ada dalam kode di atas. Bisakah Anda memberi saya kode lengkap?
Magecode
tidak ada tidak ada blok seperti itu sebaliknya saya telah membuat tipe virtual untuk itu Anda dapat memeriksa kode di.xml dan kode yang diposting di sini adalah kode lengkap itu sendiri.
mp196
Ok bisa tolong kirimi saya zip seluruh kode?
Magecode
Maaf tidak dapat mengirim zip karena kode yang dijawab di atas hanyalah sebagian kecil dari ekstensi berbayar yang kami kembangkan.
mp196
1
periksa apakah Anda menambahkan $ this-> layerResolver = $ layerResolver; di konstruk Anda untuk kelas yang ditambahkan di konstruktor file. \ Magento \ Catalog \ Model \ Layer \ Resolver $ layerResolver
mp196
2

Saya berhasil menerapkan koleksi produk khusus pada navigasi dan bilah alat berlapis laman kategori.

Sebagai contoh, saya mengambil koleksi produk-produk yang harganya kurang dari 100.

Langkah 1: Tambahkan potongan kode di bawah ini

app / code / Vendor / Module / 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>

Langkah 2: Buat plugin untuk koleksi produk

app / code / Vendor / Module / Plugin / 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;
  }
}

Langkah 3: Buat plugin untuk bilah alat

app / code / Vendor / Module / Plugin / 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;
  }

}
Dinesh Yadav
sumber
Halo, Saya telah Menggunakan Kode Anda Ini Memperbarui Koleksi Produk Correclty Tetapi tidak memperbarui FIlterList seperti Kategori, Harga, Atribut, dan juga jumlah Produk mereka. Bisakah Anda Membantu untuk ini, Ini Mendesak bagi Saya ?? @DineshYadav
Sujeet Pandit
solusi Anda bekerja dengan sempurna. Saya telah menambahkan beberapa lonceng dan peluit tambahan untuk mendengarkan kategori tertentu dan kemudian sepenuhnya menulis ulang koleksi mereka.
pixiemedia
@pixiemedia Anda dapat mengubah jawaban saya jika itu berhasil untuk Anda ☺️
Dinesh Yadav
saya sudah punya;) memang menemukan masalah kecil dengan cara - dalam kode plugin, bagian terakhir setelah yang lain istirahat hasil pencarian. komentar yang menggigit
pixiemedia
berhenti bekerja pada M2.2 - galat sql SQLSTATE [42S22]: Kolom tidak ditemukan: 1054 Kolom tidak dikenal 'e.min_price' dalam 'daftar bidang' - mengerjakan solusinya
pixiemedia
0

Saya bisa mendapatkan navigasi berlapis yang kebanyakan berfungsi untuk koleksi produk khusus pada halaman kustom. Saya mengunggah kode sumber untuk modul saya di sini . Satu-satunya masalah adalah bahwa filter Harga tidak menampilkan jumlah produk yang benar. Karena itu, saya memodifikasi tampilan navigasi berlapis untuk menyembunyikan filter Harga. Tetapi karena saya menggunakan file tampilan khusus, untuk beberapa alasan filter di sidebar tidak dapat diciutkan lagi.

Jika ada yang bisa memperbaiki masalah itu, silakan mengajukan permintaan penarikan. Saya juga mencoba mencari cara menerapkan ini untuk halaman CMS yang dibuat melalui backend Magento 2, bukan untuk halaman yang dibuat secara manual melalui xml.

R. Townley
sumber