Magento 2如何添加按选项自定义排序


22

我需要添加一个基于created_at属性的附加过滤器,以便按最新产品对产品列表进行排序。我试图使用下面的文件来计算

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

但是如何将我们的实体ID添加到getAvailableOrders()

Answers:


23

如果要使用created_atadmin-> stores->(attribute)产品中不存在的属性,因为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;        
}

仅此而已,对我而言,它就像是一种魅力。


如果有人想默认升序,则更} elseif ( $this->getCurrentDirection() == 'asc' ) {改为} else {
thdoan '16

2
另外,如果您不想使用插件,也可以$block->addOrderToAvailableOrders('created_at', 'New')在分拣器模板中使用内置的公共功能。
thdoan '16

您可以为定制商品价格分类提供解决方案吗?@Luca
Dhaduk Mitesh '18

@DhadukMitesh当然,您可以使用上面的代码,并created_at使用您的自定义价格属性代码更改属性代码
LucScu

我没有自定义价格属性。我使用默认价格排序依据。我只更改价格在排序的核心文件。我想为收藏设置我的自定义价格。但我无法在收藏中设置自定义价格。
Dhaduk Mitesh '18

19

我们可以通过使用插件来实现。请在您的模块中创建以下文件。

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>

应用程序/代码/包/ CustomToolbar /插件/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;
}
}

应用程序/代码/包/ CustomToolbar /插件/产品/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类。


这无法解决created_at且不适用于2.1.9的情况-至少对我来说
-dawhoo

您能否详细说明aroundSetCollection是如何工作的?
TheKitMurkit

未定义的变量$ collection,
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

供应商名称:Arun

模块名称:NewSorting

供应商/模块名称/registration.php

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

步骤2:您创建module.xml

供应商/模块名称/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>

步骤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步:覆盖Toolbar.php ***

供应商/模块名称/插件/产品/产品列表/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,但是当我运行upgrade命令时,它说“没有更新”。使用2.2.5。复制了以上所有内容...但是想知道您提到的Registration.php文件中有什么以及在哪里找到它?
YorkieMagento

我更新了Registration.php文件的内容路径:供应商/模块名称
/registration.php

完全按照上述方式添加了模块,前端显示了“ new”选项。似乎已经替换了“位置”选项,那是预期吗?我无法在管理面板的目录中看到该选项,因为我想将此默认选项设为...谢谢。
YorkieMagento

1

不需要写代码的方式

  1. created_at在数据库表中找到产品属性eav_attribute,将其列设置frontend_labelCreated At(默认为null)。

  2. created_at在数据库表中找到产品属性catalog_eav_attribute,将其列设置used_for_sort_by1(默认为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这是另一种简单的方法。它更改了两个无关紧要的DB字段。您也可以使用代码覆盖功能,但是覆盖的功能将在版本升级中更改,并且您必须更新自定义代码。两种方法都有优点和缺点。将自定义代码用于简单功能有点夸张。
Key Shang

@SagarParikhSGR我使用了它,它正在工作。注意使用正确attribute_id
关键尚

@KeyShang我的坏人,它运作良好,不赞成:)
Sagar Parikh SGR
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.