Magento 2 Как добавить пользовательскую сортировку по опции

22

Мне нужно добавить дополнительный фильтр на основе created_atатрибута для сортировки списка товаров по последнему продукту. Я попытался понять это, используя файл ниже

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

но как добавить наш идентификатор сущности getAvailableOrders()?

Чамал Чамикара
источник

Ответы:

23

Если вы хотите использовать такой атрибут created_at, которого нет в admin-> stores -> (attribute) product, потому что атрибуты, определенные в admin, имеют настройку 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;        
}

Вот и все, для меня работает как шарм.

LucScu
источник
Если кто-то хочет по умолчанию на возрастание, то измените } elseif ( $this->getCurrentDirection() == 'asc' ) {на } else {.
thdoan
2
Также, если вы не хотите использовать плагин, вы также можете использовать встроенную публичную функцию $block->addOrderToAvailableOrders('created_at', 'New')в шаблоне сортировщика.
thdoan
Можете ли вы найти решение для сортировки цены товара? @Luca
Дхадук Митеш,
@DhadukMitesh уверен, что вы можете просто использовать приведенный выше код и изменить код атрибута created_atс помощью своего пользовательского кода атрибута цены
LucScu
У меня нет пользовательского ценового атрибута. Я использую сортировку цены по умолчанию. Я меняю только основной файл, где сортируется цена. и я хочу установить свою цену для коллекции. но я не могу установить пользовательскую цену в коллекции.
Дхадук Митеш
19

Мы можем добиться этого с помощью плагинов. Пожалуйста, создайте следующие файлы в вашем модуле.

Приложение / код / ​​пакет / 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 / Plugin / Модель / 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 / Plugin / Продукт / 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;
    }
}

Это работает хорошо для меня без переписывания любого класса Magento.

Сумит Верма
источник
это не относится к creat_at и не работает для 2.1.9 - по крайней мере для меня
dawhoo
Не могли бы вы рассказать о том, как работает SetCollection?
TheKitMurkit
неопределенная переменная $ collection,
Джафар Пинджар
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 .

iproger
источник
Где этот код добавлен в файловую систему?
YorkieMagento
1
Зачем создавать пользовательский модуль для изменения поля БД? я не думаю, что это лучший способ.
LucScu
2

Шаг 1 : Сначала вы должны создать registration.php

Название поставщика: Арун

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

Производитель / MODULENAME / registration.php

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

Шаг 2 : Вы создаете module.xml

Производитель / MODULENAME / и т.д. / 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 : Вы создаете плагин

Производитель / MODULENAME / и т.д. / 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

Производитель / MODULENAME / Plugin / Модель / 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 : переопределить Toolbar.php ***

Производитель / MODULENAME / Plugin / Продукт / 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;
    }
}

это отлично работает

Арунпрабакаран М
источник
Любые команды для запуска в CLI после обновления этих файлов, пожалуйста?
YorkieMagento
Необходимо выполнить следующие настройки установки CLI, развертывание статического содержимого, очистку кэша, переиндексацию
Arunprabakaran M
Спасибо MSA, но когда я запускаю команду обновления, она говорит «ничего не обновлять». Использование 2.2.5. Скопировал все вышеперечисленное ... но поинтересовался, что находится в файле Registration.php, о котором вы упоминаете, и где его найти?
YorkieMagento
Я обновил путь к содержимому файла Registration.php: Vendor / Modulename / 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;
Ключ Шан
источник
Я бы не стал напрямую изменять значения в БД, особенно если это основные данные.
LucScu
@LucScu Это просто еще один более простой способ. Это изменило два поля БД, которые не имеют значения. Вы также можете использовать коды для переопределения функции, но покрываемая функция будет изменена при обновлении версии, и вам придется обновить свои пользовательские коды. Оба метода имеют свои преимущества и недостатки. Использование пользовательских кодов для простой функции немного излишне.
Ключ Шан
@SagarParikhSGR Я использовал его, и он работает. Обратите внимание на использование права attribute_id.
Ключ Шан
@KeyShang мой плохой, он работает отлично, проголосовал :)
Sagar Parikh SGR