Magento 2オプションでカスタムソートを追加する方法


21

created_at製品リストを最新の製品でソートするために、属性に基づいて追加のフィルターを追加する必要があります。私は以下のファイルを使用してそれを理解しようとしました

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

しかし、どのようにエンティティIDを追加できますgetAvailableOrders()か?

回答:


22

created_atadmin-> stores->(attribute)製品にないような属性を使用する場合、adminで定義された属性には設定Sorting in Product Listing = Yes/Noがあるため、次の2つのファイルを操作する必要があります。

\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

2
また、プラグインを使用したくない場合$block->addOrderToAvailableOrders('created_at', 'New')は、ソーターテンプレートで組み込みのパブリック関数を使用することもできます。
-thdoan

カスタム製品の価格をソートするためのソリューションはありますか?@Luca
ダダックミテシュ18

@DhadukMitesh確かに、上記のコードを使用created_atし、カスタム価格属性コードで属性コードを変更することができます
LucScu

カスタム価格属性はありません。デフォルトの価格で並べ替えを使用します。価格がソートされているコアファイルのみを変更します。コレクションのカスタム価格を設定したい。しかし、コレクションにカスタム価格を設定することはできません。
ダダックミテシュ

18

プラグインを使用して実現できます。モジュールに次のファイルを作成してください。

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 / code / Package / CustomToolbar / Plugin / Product / 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に

aroundSetCollectionがどのように機能するかについて詳しく説明していただけますか?
TheKitMurkit

未定義変数$ collection
jafar pinjar

4

Create At属性のみを使用する場合は、管理パネルの並べ替えオプションでこの属性を有効にできます。

例:

<?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セットアップアップグレード、静的コンテンツの展開、キャッシュのクリーン、
インデックス再

MSAに感謝しますが、アップグレードコマンドを実行すると、「更新するものがありません」と表示されます。2.2.5を使用します。上記のすべてをコピーしました...しかし、あなたが言及したRegistration.phpファイルには何があり、どこにあるのか疑問に思いましたか?
YorkieMagento

Registration.phpファイルのコンテンツパスを更新しました:Vendor / Modulename / registration.php
Arunprabakaran M

上記とまったく同じモジュールを追加し、「新しい」オプションがフロントエンドに表示されます。「位置」オプションを置き換えたように思われますか?このデフォルトオプションを作成したいので、管理パネルのカタログにオプションが表示されません...ありがとうございます。
YorkieMagento

0

方法はコードを書く必要はありません

  1. created_atDBテーブルeav_attributeで製品属性を見つけ、その列frontend_labelCreated At(デフォルトはnull)に設定します。

  2. created_atDBテーブル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これは、もう1つの簡単な方法です。関係のない2つのDBフィールドが変更されました。コードを使用して関数をオーバーライドすることもできますが、対象の関数はバージョンアップグレードで変更されるため、カスタムコードを更新する必要があります。どちらの方法にも長所と短所があります。単純な関数にカスタムコードを使用するのは少しやり過ぎです。
キーシャン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.