Magento 2 Come aggiungere un ordinamento personalizzato per opzione


22

Devo aggiungere un filtro aggiuntivo basato sull'attributo created_atper ordinare l'elenco dei prodotti per prodotto più recente. Ho provato a immaginarlo usando il file qui sotto

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

ma come si può aggiungere il nostro ID entità a getAvailableOrders()?

Risposte:


23

Se si desidera utilizzare un attributo del genere created_atnon presente in admin-> negozi -> (attributo) prodotto, poiché gli attributi definiti in admin hanno l'impostazione Sorting in Product Listing = Yes/No, è necessario lavorare con questi due file:

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

In Toolbar.phppuoi vedere

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

chiama getAttributeUsedForSortByArray()da Config.phpquello restituisce una matrice di attributi disponibili per ordinare la raccolta di elenchi.

Ora devi aggiungere created_atqui il tuo attributo. Come? L'ho fatto con un plugin

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

Hai inserito gli created_atattributi disponibili per ordinare, ora devi solo creare la tua raccolta personalizzata per usarla. Qui scelgo di eseguire l'override \vendor\magento\module-catalog\Block\Product\ProductList\Toolbar.php con il mio Toolbar.phpe l'overridesetCollection()

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

Questo è tutto, per me funziona come un fascino.


Se qualcuno desidera impostare il valore predefinito in ordine crescente, } elseif ( $this->getCurrentDirection() == 'asc' ) {passa a } else {.
thdoan

2
Inoltre, se non si desidera utilizzare un plug-in, è anche possibile utilizzare la funzione pubblica integrata $block->addOrderToAvailableOrders('created_at', 'New')nel modello di ordinamento.
thdoan

Puoi avere la soluzione per ordinare il prezzo del prodotto personalizzato? @Luca
Dhaduk Mitesh,

@DhadukMitesh certo, potresti semplicemente usare il codice sopra e cambiare il codice dell'attributo created_atcon il tuo codice dell'attributo del prezzo personalizzato
LucScu

Non ho un attributo di prezzo personalizzato. Uso l'ordinamento predefinito per. Cambio solo nel file core dove il prezzo è l'ordinamento. e voglio impostare il mio prezzo personalizzato per una collezione. ma non riesco a impostare il prezzo personalizzato nella raccolta.
Dhaduk Mitesh,

19

Possiamo raggiungerlo usando Plugin. Si prega di creare i seguenti file nel modulo.

app / code / Pacchetto / 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 / Pacchetto / CustomToolbar / Plugin / Modello / 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 / code / Pacchetto / CustomToolbar / Plugin / prodotto / 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;
    }
}

Questo funziona bene per me senza riscrivere nessuna lezione di Magento.


questo non si rivolge a create_at e non funziona per 2.1.9 - almeno per me
dawhoo il

Potresti per favore approfondire come funziona aroundSetCollection?
TheKitMurkit,

variabile $ non definita $ collection,
jafar pinjar

4

Se si desidera utilizzare solo l' attributo Crea in , è possibile attivare questo attributo nel pannello di amministrazione nelle opzioni di ordinamento.

Esempio:

<?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) {
            }
        }
    }
}

Questo codice da Setup / UpgradeData.php , ma sarà meglio usare invece InstallData.php .


Dove viene aggiunto questo codice nel file system?
YorkieMagento,

1
Perché creare un modulo personalizzato per modificare un campo db? non penso sia il modo migliore.
LucScu il

2

Passaggio 1 : Innanzitutto devi creare registration.php

Nome del fornitore: Arun

Nome del modulo: NewSorting

Venditore / Modulename / registration.php

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

Passaggio 2 : si crea module.xml

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

Passaggio 3 : si crea il plug-in

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

Passaggio 4 : quindi creare config.php

Venditore / Modulename / Plugin / Modello / 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;
    }
}

Passaggio 5 : sovrascrivi Toolbar.php ***

Venditore / Modulename / Plugin / prodotto / 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;
    }
}

funziona perfettamente


Eventuali comandi da eseguire nella CLI dopo aver aggiornato questi file, per favore?
YorkieMagento,

È necessario eseguire l'aggiornamento della configurazione della CLI, la distribuzione del contenuto statico, la pulizia della cache, la reindicizzazione
Arunprabakaran M

Grazie MSA ma quando eseguo il comando upgrade non dice "nulla da aggiornare". Utilizzando 2.2.5. Ho copiato tutto quanto sopra ... ma ti chiedi cosa c'è nel file Registration.php che menzioni e dove trovarlo?
YorkieMagento,

Ho aggiornato il percorso del contenuto del file Registration.php: Vendor / Modulename / registration.php
Arunprabakaran M

Modulo aggiunto esattamente come sopra e l'opzione 'nuovo' appare sul front-end. Sembra aver sostituito l'opzione "posizione" è quella prevista? Non riesco a visualizzare l'opzione nel catalogo nel pannello di amministrazione, in quanto vorrei rendere questa opzione predefinita ... Grazie.
YorkieMagento,

1

Il modo in cui non ha bisogno di scrivere codici

  1. Trova l' created_atattributo del prodotto nella tabella DB eav_attribute, imposta la sua colonna frontend_labelsu Created At(il valore predefinito è null).

  2. Trova l' created_atattributo del prodotto nella tabella DB catalog_eav_attribute, imposta la sua colonna used_for_sort_bysu 1(il valore predefinito è 0).

  3. Pulisci la cache del sito e funziona.

Esempio: cambia tabella con 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;

Non cambierei direttamente i valori di db, specialmente se si tratta di dati di base.
LucScu il

@LucScu È solo un altro modo più semplice. Ha cambiato due campi DB che non contano. È possibile utilizzare anche i codici per sovrascrivere la funzione, ma la funzione coperta verrà modificata nell'aggiornamento della versione e sarà necessario aggiornare i codici personalizzati. Entrambi i metodi presentano vantaggi e svantaggi. Utilizzare codici personalizzati per una semplice funzione è un po 'eccessivo.
Key Shang

@SagarParikhSGR L'ho usato e funziona. Presta attenzione all'uso del giusto attribute_id.
Key Shang

@KeyShang mio male, funziona perfettamente, è stato votato :)
Sagar Parikh SGR
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.