Magento 2 Як додати спеціальне сортування за опцією


22

Мені потрібно додати додатковий фільтр на основі created_atатрибуту для сортування списку продуктів за останнім продуктом. Я спробував зрозуміти це за допомогою файла нижче

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

але як можна додати ідентифікатор нашої сутності getAvailableOrders()?

Відповіді:


23

Якщо ви хочете використовувати такий атрибут, як created_atйого немає в продукті адмін-> магазини -> (атрибут), тому що атрибути, визначені в адміністраторі, мають налаштування Sorting in Product Listing = Yes/No, вам потрібно працювати з цими двома файлами:

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

У Toolbar.phpви можете бачити

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

він закликає getAttributeUsedForSortByArray()з Config.phpцього повертає масив доступних атрибутів для сортування колекції списків.

Тепер ви повинні додати свій created_atатрибут тут. Як? Я зробив це за допомогою плагіна

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

Ви вставляли created_atдоступні атрибути для сортування, тепер вам залишається лише створити власну колекцію, щоб використовувати її. Тут я вибираю перекрити \vendor\magento\module-catalog\Block\Product\ProductList\Toolbar.php моє Toolbar.phpта переотриматиsetCollection()

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

Це все, для мене працює як шарм.


Якщо хтось хоче за замовчуванням зростати, то змініть } elseif ( $this->getCurrentDirection() == 'asc' ) {на } else {.
thoan

2
Крім того, якщо ви не хочете використовувати плагін, ви також можете використовувати вбудовану загальнодоступну функцію $block->addOrderToAvailableOrders('created_at', 'New')у вашому шаблоні сортування.
thoan

Чи можете ви мати рішення для сортування замовної ціни товару? @Luca
Dhaduk Mitesh

@DhadukMitesh впевнений, що ви можете просто скористатись вищевказаним кодом та змінити код атрибута created_atзі своїм власним кодом атрибуту ціни
LucScu

У мене немає спеціального атрибуту ціни. Я використовую сортування цін за замовчуванням за. Я змінюю лише основний файл, де ціна сортується. і я хочу встановити власну ціну колекції. але я не можу встановити власну ціну в колекції.
Дахук Мітеш

19

Ми можемо досягти цього за допомогою плагінів. Створіть у своєму модулі наступні файли.

app / code / Package / CustomToolbar / тощо / 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>

додаток / код / ​​Пакет / CustomToolbar / Плагін / Модель / 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;
}
}

додаток / код / ​​Пакет / CustomToolbar / Плагін / Продукт / Список продуктів / 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;
    }
}

Це добре працює для мене, не переписуючи жодного класу Magento.


це не адресу create_at і не працює для 2.1.9 - для мене щонайменше
dawhoo

Чи можете ви, будь ласка, детальніше розповісти про те, як працює навколоSetCollection?
TheKitMurkit

невизначена змінна $ колекція,
jafar pinjar

4

Якщо ви хочете використовувати атрибут просто створити , ви можете активувати цей атрибут на панелі адміністратора в параметрах сортування.

Приклад:

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

Цей код із Setup / UpgradeData.php , але краще буде замість цього використовувати InstallData.php .


Де цей код додається у файловій системі?
YorkieMagento

1
Навіщо створювати спеціальний модуль для зміни поля DB? я не думаю, що це найкращий спосіб.
LucScu

2

Крок 1. Спершу слід створити registration.php

Назва продавця: Арун

Назва модуля: NewSorting

Постачальник / Ім’я модуля / registration.php

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

Крок 2 : Ви створюєте module.xml

Постачальник / Ім’я модуля / тощо / 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>

Крок 3 : Ви створюєте плагін

Постачальник / Ім’я модуля / 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>

Крок 4 : тоді створіть config.php

Постачальник / Ім’я модуля / Плагін / Модель / 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;
    }
}

Крок 5 : Замініть панель інструментів.php ***

Постачальник / Назва модуля / Плагін / Продукт / Список продуктів / Панель інструментів.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;
    }
}

це працює ідеально


Будь-які команди, які потрібно запустити в CLI після оновлення цих файлів, будь ласка?
YorkieMagento

Потрібно запустити наступне оновлення настройки CLI, розгортання статичного вмісту, очищення кешу,
перевстановлення

Дякую MSA, але коли я запускаю команду оновлення, вона говорить "нічого для оновлення". Використовуючи 2.2.5. Скопіював усе вищесказане ... але задумався, що це у згаданому вами файлі Registration.php і де його знайти?
YorkieMagento

Я оновив шлях вмісту файлу Registration.php: Постачальник / Ім’я модуля / registration.php
Arunprabakaran M

Доданий модуль точно так, як було зазначено вище, і опція "новий" відображається на передній частині. Здається, замінили варіант "позиції", що очікується? Я не можу побачити цю опцію в каталозі на панелі адміністратора, тому що я хотів би зробити цей параметр за замовчуванням ... Дякую.
YorkieMagento

1

Шляхи запису не потребують

  1. Знайдіть created_atатрибут продукту в таблиці БД eav_attribute, встановіть його стовпець frontend_labelна значення Created At(за замовчуванням - нуль).

  2. Знайдіть created_atатрибут продукту в таблиці БД catalog_eav_attribute, встановіть його стовпець used_for_sort_byв 1( по умовчанням 0).

  3. Очистіть кеш сайту і він працює.

Приклад: зміни таблиці на 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;

Я б безпосередньо не змінював значення db, особливо якщо це основні дані.
LucScu

@LucScu Це просто ще один простіший спосіб. Це змінило два поля БД, які не мали значення. Ви також можете використовувати коди для зміни функції, але функція, що охоплюється, буде змінена під час оновлення версії, і вам доведеться оновити власні коди. Обидва методи мають переваги та недоліки. Використовувати власні коди для простої функції - це трохи зайвої кількості.
Ключ Шан

@SagarParikhSGR Я ним користувався і він працює. Зверніть увагу на використання права attribute_id.
Ключ Шан

@KeyShang моя погана, її робота ідеально, прихильна :)
Sagar Parikh SGR
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.