Magento 2 Orders Grid にフィルター付きの列を追加する方法は?
公開: 2020-02-03多くの場合、Magento 2 ストアの管理者は、注文グリッドを使用およびカスタマイズする際に追加のオプションを必要とします。特定のすぐに使用できるパラメーターに基づくフィルタリングは、実際の課題になる可能性があります。
最近、Magento の開発者から質問がありました。 彼は Magento 2.3.1 で注文グリッドを拡張しようとしました。 Web で入手できる古い記事は役に立ちませんでした。当然のことながら、Magento では過去 2 年間で多くの変更が行われました。
彼の質問に基づいて、特定のケースの解決策を見てみましょう。
注文グリッドに、購入を完了した顧客の地域コードを含む列を追加する必要があります。 さらに、ストア管理者は、この新しく追加された列で注文をフィルター処理できる必要があります。
簡単に思えるかもしれませんが、注意すべき点がいくつかあります。 たとえば、仮想注文の場合、購入した買い物客には配送先住所がない場合があります。 または、どのように地域をリストアップしますか? 開発に着手するときは、これらすべてを考慮する必要があります。 前述の質問に基づいて、次のように仮定します。
- 仮想製品には配送地域がありません (「null」)。 これは、このパラメーターに基づいてそれらを選択するのに役立ちます。
- デフォルトの Magento 2 と同様に、リージョンがリストされ、ラベルに変換されていないコードの外観になります。
*この記事の最後に、GitHub でオープン アクセスのモジュールへのリンクが表示されることに注意してください。 ただし、この記事を読み終えることができない場合は、この段落にリンクを含めます: https://github.com/mageworx/articles-extended-orders-grid.
しかしながら, 時間がないにもかかわらず, 読み進めることをお勧めします.
したがって、注文グリッドに新しい列を追加するには、次のことを行う必要があります。
目次
- 1. 新しいモジュールを作成する
- 2.グリッドに列を追加します
- 説明
- 3.列にデータを追加する
- 余分な列を追加する方法は?
- [更新] 注文商品情報を含む列を追加する方法は?
1. 新しいモジュールを作成する
まず、モジュールとベンダー名を決めましょう。 まあ、ベンダー名を選ぶ必要はありません - それは MageWorx です (選択肢があるかのように、冗談です)。 モジュール名を選択する必要があります。 ExtendedOrdersGridとします (ところで、Magento 2 には同じ名前の拡張機能があります)。 実際、名前空間で MageWorx をベンダー名として使用しても、無料サポートを要求する権利はありません。 とにかく、サポート チームのメンバーが良い週末を過ごした場合でも、月曜日に試してみることができます。
次のディレクトリを作成しましょう: `app/code/MageWorx/ExtendedOrdersGrid`。 モジュールを登録するには、いくつかの標準ファイルが必要です。
> registration.php php <?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'MageWorx_ExtendedOrdersGrid', __DIR__ ); > composer.json json { "name": "mageworx/module-extended-orders-grid", "description": "Extended Orders Grid Extension", "require": { "magento/module-ui" : ">=100.1.0 < 102", "magento/module-sales" : ">=100.0.0 <103" }, "type": "magento2-module", "version": "1.0.0", "license": [ "OSL-3.0", "AFL-3.0" ], "autoload": { "files": [ "registration.php" ], "psr-4": { "MageWorx\\ExtendedOrdersGrid\\": "" } } } > etc/module.xml 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="MageWorx_ExtendedOrdersGrid" setup_version="1.0.0"> <sequence> <module name="Magento_Sales"/> <module name="Magento_Ui"/> </sequence> </module> </config>
IDE に自動的に追加される著作権を削除したことに注意してください。 したがって、問題なくこのコードを使用できます。 ?
次に、いくつかのコマンドを実行します。
> sudo -u www-data php bin/magento module:enable MageWorx_ExtendedOrdersGrid > sudo -u www-data php bin/magento setup:upgrade
そして出来上がり! これで、モジュールが Magento 2 で表示されます。 リモート サーバーで作業している場合は、テストの前にファイルを転送することを忘れないでください。
2.グリッドに列を追加します
次に、Magento 2 UI を使用して、標準グリッドに新しい列を追加しましょう。 そのために、ファイルを作成します。
> view/adminhtml/ui_component/sales_order_grid.xml
次の内容で(その意味については後で説明します):
xml <?xml version="1.0" encoding="UTF-8"?> <listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> <columns name="sales_order_columns"> <column name="code"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> <item name="label" xsi:type="string" translate="true">Region Code</item> <item name="sortOrder" xsi:type="number">60</item> <item name="align" xsi:type="string">left</item> <item name="dataType" xsi:type="string">text</item> <item name="visible" xsi:type="boolean">true</item> <item name="filter" xsi:type="string">text</item> </item> </argument> </column> </columns> </listing>
ここでは、名前がどこからも取り出されていないことを指定する必要があります。 経験豊富な開発者にとっては明らかですが、Magento 2 しか知らない人のために、この段落の最後にいくつかの説明を追加します。
標準の `columns` ノードを使用してグリッドに列を追加しました。ここで、'code' 名の下に新しい列も追加されます。 次に、列の属性をグリッドに書き込みましょう。
1)コンポーネント. これは、この列の作成と処理を担当する JS クラスです。 次のアドレスの Magento_Ui モジュールにあります。
`vendor/magento/module-ui/view/base/web/js/grid/columns/column.js`
実際、好奇心旺盛な開発者の方は、他の実現方法も見てください。 そこにはエキサイティングなものがたくさんあります。
2)ラベル。 これは列名を含む行で、エンド ユーザーに表示されます。 `translate` プロパティが設定されている場合は、忘れずに i18n ローカリゼーション ファイルに追加してください。 ?
3)ソート順。 これは、グリッド内の列の位置です。 ストア管理者が管理したことのない Magento 2 にモジュールがインストールされている場合は、影響があります。 それ以外の場合、使用されている Magento 2 では、何をしても列がリストの最後に追加されます。
4)整列します。 これは、列の内容を揃えることを意味します。 それは明らかだと思います。
5)データ型。 これは、操作するデータ型です。 私たちの場合、それは単なるテキスト行です。 ただし、たとえば製品の数量について言えば、数値だけでなく、リストまたはブール値でもかまいません。
6)見える。 これは、グリッドが以前に使用されたかどうかに大きく依存しますが、列の可視性に他なりません。
グリッドに関するすべてのデータは、Magento データベースの「ui_bookmark」テーブルに保存されます。 したがって、モジュールのインストール時に変更されたグリッドの列に関する記録がない場合、奇跡は期待できません。
7)フィルター. こちらはフィルタータイプ。 ここでは、通常のテキストと同様にフィルタリングを行うように指定しました。 コードを実行すると、MySQL `LIKE %value%` 条件に変換されます。
説明
簡単に言うと、拡張された UI コンポーネントの名前はオリジナルの名前と一致している必要があります。 私たちの場合、それは `vendor/magento/module-sales/view/adminhtml/ui_component/sales_order_grid.xml` であり、`view/adminhtml/ui_component/sales_order_grid.xml` モジュール ルートから計算されます。
UI グリッド自体は、次のように「vendor/magento/module-sales/view/adminhtml/layout/sales_order_index.xml」レイアウトを使用して必要なコントローラーに追加されます。
xml <?xml version="1.0"?> <!-- /** * Copyright Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <update handle="styles"/> <body> <referenceContainer name="content"> <uiComponent name="sales_order_grid"/> </referenceContainer> </body> </page>
これは、ブロックの場合と同様に、*「sales_order_grid」という名前でこの UI コンポーネントをページ コンテンツに追加する*ことを意味します。 ただし、ブロックの代わりに、属性と制限を備えた `uiComponent` があります。
次に、次のコマンドを使用して Magento 2 キャッシュをクリアします。
> sudo -u www-data php bin/magento cache:clean config
注文グリッドで結果を確認します。
3.列にデータを追加する
列が表示されていることに気付いたかもしれませんが、その内容は期待どおりではないように見えます...そこにはデータがまったく表示されていません。 当然のことながら、何も追加していないため、コンテンツはありません。
コラムの記入に役立つ簡単なプラグインの作成に取り掛かりましょう。 そのために、グリッド コレクション クエリをキャッチして、必要なテーブルとグリッド内で結合を作成しましょう。 プラグインは次のようになります。
> app/code/MageWorx/ExtendedOrdersGrid/Plugin/AddDataToOrdersGrid.php
php <?php namespace MageWorx\ExtendedOrdersGrid\Plugin; /** * Class AddDataToOrdersGrid */ class AddDataToOrdersGrid { /** * @var \Psr\Log\LoggerInterface */ private $logger; /** * AddDataToOrdersGrid constructor. * * @param \Psr\Log\LoggerInterface $customLogger * @param array $data */ public function __construct( \Psr\Log\LoggerInterface $customLogger, array $data = [] ) { $this->logger = $customLogger; } /** * @param \Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory $subject * @param \Magento\Sales\Model\ResourceModel\Order\Grid\Collection $collection * @param $requestName * @return mixed */ public function afterGetReport($subject, $collection, $requestName) { if ($requestName !== 'sales_order_grid_data_source') { return $collection; } if ($collection->getMainTable() === $collection->getResource()->getTable('sales_order_grid')) { try { $orderAddressTableName = $collection->getResource()->getTable('sales_order_address'); $directoryCountryRegionTableName = $collection->getResource()->getTable('directory_country_region'); $collection->getSelect()->joinLeft( ['soa' => $orderAddressTableName], 'soa.parent_id = main_table.entity_id AND soa.address_type = \'shipping\'', null ); $collection->getSelect()->joinLeft( ['dcrt' => $directoryCountryRegionTableName], 'soa.region_id = dcrt.region_id', ['code'] ); } catch (\Zend_Db_Select_Exception $selectException) { // Do nothing in that case $this->logger->log(100, $selectException); } } return $collection; } }
次のクラスを参照します。
`Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory`
> etc/adminhtml/di.xml xml <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <!-- Plugins --> <!-- Adds additional data to the orders grid collection --> <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"> <plugin name="mageworx_extended_orders_grid_add_data_to_orders_grid" type="MageWorx\ExtendedOrdersGrid\Plugin\AddDataToOrdersGrid" sortOrder="10" disabled="false"/> </type> </config>
プラグインは次の方法で実行されます。
絶対にすべてのコレクションをキャッチするので、必要な `sales_order_grid` テーブルに検証を追加しましょう。 それが見つかり、Magento がこれに関するデータを取得しようとすると、「order_id」(「sales_order_grid」テーブルの「entity_id」と「sales_order_address」テーブルの「parent_id」) によって「sales_order_address」アドレスとテーブルを結合します ( `soa` エイリアス))。 これで、顧客の注文の配送先住所データにアクセスできるようになりました。これを使用して「region_id」を決定できます。 これは、「sales_order_address」テーブルに番号として配置されています。 この番号は、`directory_country_region` テーブル (`dcrt` エイリアス) のインデックスに対応します。 上記のようにテーブルからこの地域コードが必要なので、「コード」列を接続しましょう。 この正確な列が出力されます (`sales_order_grid.xml` の `column` 値に対応)。
次に、キャッシュをクリアします。
> sudo -u www-data php bin/magento cache:clean config
管理パネルから注文グリッドにログインします。 すべてが正しく行われると、地域コードが表示されます。
モジュールへの無料アクセスは、GitHub で入手できます: https://github.com/mageworx/articles-extended-orders-grid。
重要な補足事項!
この列にデータを追加するには、「your_column_name」列と、コレクションの作成時に追加されたすべての必要なデータを取得する必要があります。 つまり、別のことを行う必要があります。テーブル名を置き換えて、独自の結合を記述します。 また、必要に応じて「sales_order_grid.xml」ファイルの列名を編集することを忘れないでください。
余分な列を追加する方法は?
もう 1 つ列を追加する場合は、次の Git コミットに記載されているガイドラインに従ってください: https://github.com/mageworx/articles-extended-orders-grid/commit/d31c364a25ce493ab64731c5ca0481e146dbbac3
そこで、 shipping
タイプの住所のsales_order_address
テーブルからtelephone
列をグリッドに追加しました。 コミット コードでわかるように、大幅なコード変更は必要ありませんでした。
さらに、これらの列は、標準の「注文グリッド」インターフェイスから正常にエクスポートできます。
「電話」列のグリッドは次のようになります。
以下のスクリーンショットでは、.csv ファイルにエクスポートされた同じ注文を確認できます。
[更新] 注文商品情報を含む列を追加する方法は?
ご存じのように、すべての注文には、1 から数え切れないほどの数量のアイテムがあります (そう、商人の夢です)。 しかし、その情報を注文グリッドに表示して、検索を開始したり、分析をより簡単に実行したりするにはどうすればよいでしょうか?
前に行ったように列を追加することはできません。その場合、各行に 1 つの製品名または SKU しか取得できないためです。 あるいは、注文記録が重複してしまう……そんな面倒なことも必要ありません。
したがって、どうすれば正しい方法でそれを行うことができるかを説明しようと思います (私の意見では)。
注文グリッドに「製品名」データ列が必要だとします。
最初に、以前に行ったように、 sales_order_grid
定義に新しい列を追加しましょう。
<columns> .... <column name="name"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/column</item> <item name="filter" xsi:type="string">text</item> <item name="label" xsi:type="string" translate="true">Product Name</item> <item name="visible" xsi:type="boolean">false</item> <item name="sortOrder" xsi:type="number">70</item> </item> </argument> </column> </columns>
次に、必要なのは、新しい列に対して適切なクエリを作成することだけです。 その注文で購入された各製品の名前をコンマで区切って含め、その列の値で検索する機能などを含める必要がありますmageworx_extended_orders_grid_add_data_to_orders_grid
プラグインで新しいメソッドを作成しましょう。
/** * Adds products name column to the orders grid collection * * @param OrderGridCollection $collection * @return OrderGridCollection */ private function addProductsNameColumn(OrderGridCollection $collection): OrderGridCollection { return $collection; }
元のメソッド本体内でそのメソッドに名前を付けます。
if ($collection->getMainTable() === $collection->getResource()->getTable('sales_order_grid')) { try { $orderAddressTableName = $collection->getResource()->getTable('sales_order_address'); ... // Add product's name column $this->addProductsNameColumn($collection); } catch (\Zend_Db_Select_Exception $selectException) { ...
1 つの列で必要なデータを取得するには、個々の選択でorder_id
とname
(製品名) の 2 つの列を持つサブ選択を作成する必要があります。これは後でメイン コレクションに結合できます。
// Get original table name $orderItemsTableName = $collection->getResource()->getTable('sales_order_item'); // Create new select instance $itemsTableSelectGrouped = $collection->getConnection()->select(); // Add table with columns which must be selected (skip useless columns) $itemsTableSelectGrouped->from( $orderItemsTableName, [ 'name' => new \Zend_Db_Expr('GROUP_CONCAT(DISTINCT name SEPARATOR \',\')'), 'order_id' => 'order_id' ] ); // Group our select to make only one column for one order $itemsTableSelectGrouped->group('order_id');
説明:
-
$collection->getConnection()->select()
行は、新しいMagento\Framework\Db\Select
インスタンスを作成します。
内部に独自のデータがあるため、コレクションからの元の選択を使用できず、変更するとエラーが発生するため、これが必要です。 -
name
列には、指定された順序のすべての製品名が含まれている必要があります。つまり、\Zend_Db_Expr('GROUP_CONCAT(DISTINCT name SEPARATOR \',\')')
式を使用してグループ化する必要があります。 そのために、後で選択にgroup('order_id')
を追加します。 グループ化しないと、GROUP_CONCAT
関数を使用できません。
これで、副選択をメイン コレクションに追加できます。これがaddProductsNameColumn
メソッドの論理的な終わりになります。
// Add our sub-select to main collection with only one column: name $collection->getSelect() ->joinLeft( ['soi' => $itemsTableSelectGrouped], 'soi.order_id = main_table.entity_id', ['name'] ); return $collection;
説明:
-
soi
は疑似テーブルのエイリアスです。 -
order_id
は、メイン テーブル (グリッド) を注文アイテム データにリンクするために使用するキーです。 -
['name']
は、他の情報が必要ないため、結果に追加される唯一の列です。
最終結果は、その例の公式リポジトリで入手できます。
特定のコミットへのリンクは次のとおりです。
ステージング ホストでその列がどのように表示されるかを次に示します。
エクスポートの結果 (CSV) は次のとおりです。
「ブラック」製品で注文を検索しようとすると、クエリは次のようになります (開発ホスト上):
SELECT main_table
.*, soat
. telephone
、 dcrt
。 code
、 soi
。 name
FROM sales_order_grid
AS main_table
LEFT JOIN sales_order_address
AS soat
ON soat.parent_id = main_table.entity_id AND soat.address_type = 'shipping'
LEFT JOIN directory_country_region
AS dcrt
ON soat.region_id = dcrt.region_id
LEFT JOIN (SELECT GROUP_CONCAT(DISTINCT name SEPARATOR ',') AS name
, sales_order_item
. order_id
FROM sales_order_item
GROUP BY order_id
) AS soi
ON soi.order_id = main_table.entity_id
どこsoi
。 name
LIKE '%Black%'
明らかに、これはデータを出力する最速の方法ではありません。 ただし、それがおそらく最も簡単な方法です。 最良の方法は、別のテーブル (order_id、products_name) の別の列に製品名に関するデータを蓄積し、余分なグループ化やサブセレクションなしでこのテーブルを追加することです。
そのために、グループ ('order_id') を select に追加します (メソッド コードの最後に)。
select は要素を意味します。
グループは選択方法を意味します。
それだけだと思います。 ご質問やご要望がございましたら、コメント欄にコメントを残してください。