Magento 2 Cara menambahkan opsi urutkan berdasarkan pilihan

22

Saya perlu menambahkan filter tambahan berdasarkan created_atatribut untuk menyortir daftar produk berdasarkan produk terbaru. Saya mencoba mencari menggunakan file di bawah ini

app/design/frontend/Vendor/ThemeName/Magento_Catalog/templates/product/list/toolbar/sorter.phtml  

tetapi bagaimana cara menambahkan id entitas kita getAvailableOrders()?

Chamal Chamikara
sumber

Jawaban:

23

Jika Anda ingin menggunakan atribut seperti created_atitu tidak ada di admin-> toko -> (atribut) produk, karena atribut yang didefinisikan dalam admin memiliki pengaturan Sorting in Product Listing = Yes/No, Anda harus bekerja dengan dua file ini:

\vendor\magento\module-catalog\Block\Product\ProductList\Toolbar.php \vendor\magento\module-catalog\Model\Config.php

Di dalam Toolbar.phpkamu bisa melihat

$this->_availableOrder = $this->_catalogConfig->getAttributeUsedForSortByArray();

itu panggilan getAttributeUsedForSortByArray()dari Config.phpyang mengembalikan berbagai atribut yang tersedia untuk mengurutkan koleksi daftar.

Sekarang, Anda harus menambahkan created_atatribut Anda di sini. Bagaimana? Saya melakukannya dengan sebuah plugin

/**
 * Add sort order option created_at to frontend
 */
public function afterGetAttributeUsedForSortByArray(
    \Magento\Catalog\Model\Config $catalogConfig,
    $options
) {
    $options['created_at'] = __('New');
    return $options;
}

Anda memasukkan created_atatribut yang tersedia untuk disortir, sekarang Anda hanya perlu membangun koleksi khusus untuk menggunakannya. Di sini saya memilih untuk menimpa \vendor\magento\module-catalog\Block\Product\ProductList\Toolbar.php dengan milik saya Toolbar.phpdan menimpanyasetCollection()

/**
 * Set collection to pager
 *
 * @param \Magento\Framework\Data\Collection $collection
 * @return $this
 */
 public function setCollection($collection) {
    $this->_collection = $collection;
    $this->_collection->setCurPage($this->getCurrentPage());

    // we need to set pagination only if passed value integer and more that 0
    $limit = (int)$this->getLimit();
    if ($limit) {
        $this->_collection->setPageSize($limit);
    }

    // switch between sort order options
    if ($this->getCurrentOrder()) {
        // create custom query for created_at option
        switch ($this->getCurrentOrder()) {
            case 'created_at':
                if ($this->getCurrentDirection() == 'desc') {
                    $this->_collection
                        ->getSelect()
                        ->order('e.created_at DESC');
                } elseif ($this->getCurrentDirection() == 'asc') {
                    $this->_collection
                        ->getSelect()
                        ->order('e.created_at ASC');           
                }
                break;
            default:
                $this->_collection->setOrder($this->getCurrentOrder(), $this->getCurrentDirection());
                break;
        }
    }

    // echo '<pre>';
    // var_dump($this->getCurrentOrder());
    // var_dump((string) $this->_collection->getSelect());
    // die;

    return $this;        
}

Itu saja, bagi saya bekerja seperti pesona.

LucScu
sumber
Jika ada yang ingin secara default naik, maka ubah } elseif ( $this->getCurrentDirection() == 'asc' ) {ke } else {.
thdoan
2
Selain itu, jika Anda tidak ingin menggunakan plugin, Anda juga dapat menggunakan fungsi publik $block->addOrderToAvailableOrders('created_at', 'New')bawaan di templat penyortir Anda.
thdoan
Bisakah Anda memiliki solusi untuk menyortir harga produk khusus? @Luca
Dhaduk Mitesh
@DhadukMitesh yakin, Anda bisa menggunakan kode di atas dan mengubah kode atribut created_atdengan kode atribut harga khusus Anda
LucScu
Saya tidak memiliki atribut harga khusus. Saya menggunakan harga standar berdasarkan. Saya hanya mengubah file inti di mana harga disortir. dan saya ingin menetapkan harga khusus untuk koleksi. tapi saya tidak bisa menetapkan harga khusus dalam koleksi.
Dhaduk Mitesh
19

Kita dapat mencapainya dengan menggunakan Plugin. Silakan buat file berikut di modul Anda.

app / code / Package / CustomToolbar / etc / di.xml

<type name="Magento\Catalog\Model\Config">
    <plugin name="Package_CustomToolbar::addCustomOptions" type="Package\CustomToolbar\Plugin\Model\Config" />
</type>
<type name="Magento\Catalog\Block\Product\ProductList\Toolbar">
    <plugin name="Package_CustomToolbar::addPriceDecendingFilterInToolbar" type="Package\CustomToolbar\Plugin\Product\ProductList\Toolbar" />
</type>

app / code / Package / CustomToolbar / Plugin / Model / Config.php

namespace Package\CustomToolbar\Plugin\Model;
use Magento\Store\Model\StoreManagerInterface;
class Config
{
    protected $_storeManager;

public function __construct(
    StoreManagerInterface $storeManager
) {
    $this->_storeManager = $storeManager;

}

/**
 * Adding custom options and changing labels
 *
 * @param \Magento\Catalog\Model\Config $catalogConfig
 * @param [] $options
 * @return []
 */
public function afterGetAttributeUsedForSortByArray(\Magento\Catalog\Model\Config $catalogConfig, $options)
{
    $store = $this->_storeManager->getStore();
    $currencySymbol = $store->getCurrentCurrency()->getCurrencySymbol();

    //Remove specific default sorting options
    unset($options['position']);
    unset($options['name']);
    unset($options['price']);

    //Changing label
    $customOption['position'] = __('Relevance');

    //New sorting options
    $customOption['price_desc'] = __($currencySymbol.' (High to Low)');
    $customOption['price_asc'] = __($currencySymbol.' (Low to High)');

    //Merge default sorting options with custom options
    $options = array_merge($customOption, $options);

    return $options;
}
}

app / kode / Paket / CustomToolbar / Plugin / Produk / ProductList / Toolbar.php

namespace Package\CustomToolbar\Plugin\Product\ProductList;
class Toolbar
{
    /**
     * Plugin
     *
     * @param \Magento\Catalog\Block\Product\ProductList\Toolbar $subject
     * @param \Closure $proceed
     * @param \Magento\Framework\Data\Collection $collection
     * @return \Magento\Catalog\Block\Product\ProductList\Toolbar
     */
    public function aroundSetCollection(
        \Magento\Catalog\Block\Product\ProductList\Toolbar $subject,
        \Closure $proceed,
        $collection
    ) {
        $currentOrder = $subject->getCurrentOrder();
        $result = $proceed($collection);

        if ($currentOrder) {
            if ($currentOrder == 'price_desc') {
                $subject->getCollection()->setOrder('price', 'desc');
            } elseif ($currentOrder == 'price_asc') {
                $subject->getCollection()->setOrder('price', 'asc');
            }
        }

        return $result;
    }
}

Ini bekerja dengan baik untuk saya tanpa menulis ulang kelas Magento.

Sumit Verma
sumber
ini tidak membahas Created_at dan tidak berfungsi untuk 2.1.9 - setidaknya untuk saya
dawhoo
Bisakah Anda menguraikan bagaimana sekitarSetCollection bekerja?
TheKitMurkit
variabel $ koleksi tidak terdefinisi,
jafar pinjar
4

Jika Anda ingin menggunakan atribut Create At saja , Anda dapat mengaktifkan atribut ini di panel admin dalam opsi penyortiran.

Contoh:

<?php

namespace Vendor\Module\Setup;

use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\UpgradeDataInterface;

class UpgradeData implements UpgradeDataInterface
{
    protected $eavSetupFactory;

    /**
     * UpgradeData constructor.
     *
     * @param EavSetupFactory $eavSetupFactory
     */
    public function __construct(
        EavSetupFactory $eavSetupFactory
    ) {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    /**
     * @param ModuleDataSetupInterface $setup
     * @param ModuleContextInterface $context
     */
    public function upgrade(
        ModuleDataSetupInterface $setup,
        ModuleContextInterface $context
    ) {
        /** @var EavSetup $eavSetup */
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

        if (version_compare($context->getVersion(), '2.1.1', '<')) {
            try {
                $entityType = $eavSetup->getEntityTypeId('catalog_product');
                $label = 'Created At';
                $eavSetup->updateAttribute($entityType, 'created_at', 'frontend_label', $label, null);
                $eavSetup->updateAttribute($entityType, 'created_at', 'used_for_sort_by', 1, null);
            } catch (LocalizedException $e) {
            }
        }
    }
}

Kode ini dari Setup / UpgradeData.php , tetapi akan lebih baik menggunakan InstallData.php sebagai gantinya.

iproger
sumber
Di mana kode ini ditambahkan dalam sistem file?
YorkieMagento
1
Mengapa membuat modul khusus untuk mengubah bidang db? saya pikir itu bukan cara terbaik.
LucScu
2

Langkah 1 : Pertama, Anda harus membuat registrasi.php

Nama penjual: Arun

Nama modul: NewSorting

Vendor / Modulename / registration.php

<?php \Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE, 'Arun_NewSorting',
__DIR__
);?>

Langkah 2 : Anda membuat module.xml

Vendor / Modulename / etc / module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Arun_NewSorting" setup_version="0.0.1">
        <sequence>
            <module name="Magento_Catalog"/>
        </sequence>
    </module>
</config>

Langkah 3 : Anda membuat plugin

Vendor / Modulename / 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\Config">
        <plugin name="Arun_NewSorting::addCustomOptions" type="Arun\NewSorting\Plugin\Model\Config" />
    </type>
    <type name="Magento\Catalog\Block\Product\ProductList\Toolbar">
        <plugin name="Arun_NewSorting::addPriceDecendingFilterInToolbar" type="Arun\NewSorting\Plugin\Product\ProductList\Toolbar" />
    </type>
</config>

Langkah 4 : lalu buat config.php

Vendor / Modulename / Plugin / Model / Config.php

<?php
namespace Arun\NewSorting\Plugin\Model;

use Magento\Store\Model\StoreManagerInterface;

class Config  {


    protected $_storeManager;

    public function __construct(
        StoreManagerInterface $storeManager
    ) {
        $this->_storeManager = $storeManager;
    }


    public function afterGetAttributeUsedForSortByArray(\Magento\Catalog\Model\Config $catalogConfig, $options)
    {
        $store = $this->_storeManager->getStore();
        $currencySymbol = $store->getCurrentCurrency()->getCurrencySymbol();

        // Remove specific default sorting options
        $default_options = [];
        $default_options['name'] = $options['name'];

        unset($options['position']);
        unset($options['name']);
        unset($options['price']);

        //Changing label
        $customOption['position'] = __( 'Relevance' );

        //New sorting options
        $customOption['created_at'] = __( ' New' );


        $customOption['name'] = $default_options['name'];

        //Merge default sorting options with custom options
        $options = array_merge($customOption, $options);

        return $options;
    }
}

Langkah 5 : Ganti Toolbar.php ***

Vendor / Modulename / Plugin / Produk / ProductList / Toolbar.php

<?php
namespace Arun\NewSorting\Plugin\Product\ProductList;

class Toolbar
{

    public function aroundSetCollection(
        \Magento\Catalog\Block\Product\ProductList\Toolbar $subject,
        \Closure $proceed,
        $collection
    ) {
        $currentOrder = $subject->getCurrentOrder();
        $result = $proceed($collection);

        if ($currentOrder) {
            if ($currentOrder == 'created_at') {
                $subject->getCollection()->setOrder('created_at', 'desc');
            } 
        }

        return $result;
    }
}

ini bekerja dengan sempurna

Arunprabakaran M
sumber
Adakah perintah yang harus dijalankan di CLI setelah memperbarui file-file ini?
YorkieMagento
Perlu dijalankan mengikuti peningkatan pengaturan CLI, penyebaran konten statis, pembersihan cache,
pengindeksan ulang
Terima kasih MSA tetapi ketika saya menjalankan perintah upgrade dikatakan 'tidak ada pembaruan'. Menggunakan 2.2.5. Menyalin semua hal di atas ... tetapi bertanya-tanya apa yang ada dalam file Registration.php yang Anda sebutkan dan di mana menemukannya?
YorkieMagento
Saya memperbarui path file file Registration.php: Vendor / Modulename / registration.php
Arunprabakaran M
Modul yang ditambahkan persis seperti di atas dan opsi 'baru' muncul di ujung depan. Tampaknya telah menggantikan opsi 'posisi' yang diharapkan? Saya tidak dapat melihat opsi dalam katalog di panel admin, karena saya ingin membuat opsi default ini ... Terima kasih.
YorkieMagento
1

Caranya tidak perlu menulis kode

  1. Temukan created_atatribut produk dalam tabel DB eav_attribute, setel kolomnya frontend_labelke Created At(standarnya adalah nol).

  2. Temukan created_atatribut produk dalam tabel DB catalog_eav_attribute, setel kolomnya used_for_sort_byke 1(standarnya adalah 0).

  3. Bersihkan cache situs dan berfungsi.

Contoh: ubah tabel dengan mysql

# Get the attribute_id of 'created_at'
select attribute_id from eav_attribute where attribute_code = 'created_at' and entity_type_id=4;

# Set frontend_label
update eav_attribute set frontend_label = 'Created At' where attribute_id=112;

# Set used_for_sort_by
update catalog_eav_attribute set used_for_sort_by = 1 where attribute_id=112;
Key Shang
sumber
Saya tidak akan secara langsung mengubah nilai-nilai db, terutama jika itu adalah data inti.
LucScu
@LucScu Ini hanyalah cara lain yang lebih mudah. Itu mengubah dua bidang DB yang tidak masalah. Anda bisa menggunakan kode untuk mengabaikan fungsi juga, tetapi fungsi yang dicakup akan diubah dalam peningkatan versi, dan Anda harus memperbarui kode khusus Anda. Kedua metode memiliki kelebihan dan kekurangan. Gunakan kode kustom untuk fungsi sederhana sedikit berlebihan.
Key Shang
@ SagarParikhSGR Saya menggunakannya dan berfungsi. Perhatikan penggunaan yang benar attribute_id.
Key Shang
@KeyShang my bad, ini bekerja dengan sempurna, terangkat :)
Sagar Parikh SGR