Wie füge ich eine Spalte mit Filter zum Magento 2 Order Grid hinzu?
Veröffentlicht: 2020-02-03Häufig benötigen Administratoren von Magento 2-Shops zusätzliche Optionen, wenn es um die Verwendung und Anpassung des Bestellrasters geht – das Filtern auf der Grundlage eines bestimmten Standardparameters kann zu einer echten Herausforderung werden.
Kürzlich hat mich ein Magento-Entwickler mit einer Frage kontaktiert. Er versuchte, das Bestellraster auf Magento 2.3.1 zu erweitern. Die alten Posts aus dem Netz halfen nicht weiter – natürlich hat sich in Magento seit den letzten zwei Jahren viel verändert.
Aufgrund seiner Frage biete ich Ihnen an, sich die Lösung für einen konkreten Fall anzuschauen:
Wir müssen eine Spalte – mit einem Regionalcode eines Kunden, der einen Kauf abgeschlossen hat – zum Bestellraster hinzufügen. Darüber hinaus muss ein Geschäftsadministrator die Möglichkeit haben, Bestellungen nach dieser neu hinzugefügten Spalte zu filtern.
Es mag einfach erscheinen, aber es gibt ein paar Dinge, auf die es sich zu achten lohnt. Beispielsweise hat ein Käufer, der einen Kauf getätigt hat, möglicherweise keine Lieferadresse – im Falle einer virtuellen Bestellung. Oder wie sollen wir die Regionen auflisten? All dies sollte bei der Entwicklung berücksichtigt werden. Nehmen wir basierend auf den zuvor erwähnten Fragen an:
- Virtuelle Produkte haben keine Lieferregion („null“). Dies hilft Ihnen bei der Auswahl basierend auf diesem Parameter,
- Regionen werden aufgelistet und sehen sich Codes an, ohne sie in Labels umzuwandeln, genau wie im Standard-Magento 2.
*Bitte beachten Sie, dass am Ende dieses Artikels ein Link zum Modul mit offenem Zugriff auf GitHub vorhanden sein wird. Ich füge den Link jedoch in diesen Absatz ein, wenn Sie es nicht schaffen, diesen Artikel fertigzustellen: https://github.com/mageworx/articles-extended-orders-grid.
Trotz des Zeitmangels ermutige ich Sie jedoch, weiterzulesen.?
Um also eine neue Spalte zum Auftragsraster hinzuzufügen, müssen Sie:
Inhaltsverzeichnis
- 1. Erstellen Sie ein neues Modul
- 2. Fügen Sie dem Raster eine Spalte hinzu
- Erläuterungen
- 3. Fügen Sie der Spalte Daten hinzu
- Wie füge ich eine zusätzliche Spalte hinzu?
- [Aktualisieren] Wie füge ich eine Spalte mit Bestellartikelinformationen hinzu?
1. Erstellen Sie ein neues Modul
Lassen Sie uns zunächst die Modul- und Herstellernamen festlegen. Nun, ich muss keinen Anbieternamen wählen – es ist MageWorx (als ob ich eine Wahl hätte, nur ein Scherz). Ich kann immer noch den Modulnamen wählen. Lassen Sie es ExtendedOrdersGrid sein (übrigens haben wir eine gleichnamige Erweiterung für Magento 2). Tatsächlich gibt Ihnen die Verwendung von MageWorx als Anbietername im Namespace nicht das Recht, kostenlosen Support anzufordern. Wie auch immer, wenn unsere Support-Team-Mitglieder ein gutes Wochenende hatten, kannst du es trotzdem am Montag versuchen.?
Lassen Sie uns das folgende Verzeichnis erstellen: `app/code/MageWorx/ExtendedOrdersGrid`. Um ein Modul zu registrieren, benötigen wir einige Standarddateien:
> 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>
Es ist wichtig zu beachten, dass ich das Urheberrecht, das meiner IDE automatisch hinzugefügt wird, abgeschnitten habe. So können Sie diesen Code problemlos verwenden. ?
Führen Sie dann einige Befehle aus:
> sudo -u www-data php bin/magento module:enable MageWorx_ExtendedOrdersGrid > sudo -u www-data php bin/magento setup:upgrade
Und voila! Jetzt ist unser Modul in Magento 2 zu sehen! Oh, wenn Sie auf einem Remote-Server arbeiten, vergessen Sie nicht, die Dateien vor dem Testen zu übertragen.
2. Fügen Sie dem Raster eine Spalte hinzu
Lassen Sie uns dann mit der Magento 2-Benutzeroberfläche eine neue Spalte zum Standardraster hinzufügen. Erstellen Sie dazu eine Datei:
> view/adminhtml/ui_component/sales_order_grid.xml
mit folgendem Inhalt (ihre Bedeutung werden wir weiter besprechen):
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>
Hier müssen Sie angeben, dass der Name nirgendwo herausgenommen wird. Für erfahrene Entwickler ist das klar, aber für diejenigen, die erst Magento 2 kennenlernen, füge ich am Ende dieses Absatzes einige Erläuterungen hinzu.
Wir haben einen standardmäßigen "Spalten"-Knoten verwendet, um Spalten zum Raster hinzuzufügen, wobei auch eine neue Spalte unter dem Namen "Code" hinzugefügt werden soll. Als nächstes schreiben wir die Attribute unserer Spalte in das Raster:
1) Komponente . Dies ist eine JS-Klasse, die für die Erstellung und Verarbeitung dieser Spalte verantwortlich ist. Es befindet sich im Magento_Ui-Modul unter der folgenden Adresse:
`vendor/magento/module-ui/view/base/web/js/grid/columns/column.js`
Wenn Sie ein neugieriger Entwickler sind, werfen Sie in der Tat auch einen Blick auf andere Realisierungen. Da gibt es jede Menge spannende Sachen.
2) Etikett. Dies ist eine Zeile mit einem Spaltennamen, der einem Endbenutzer angezeigt wird. Vergessen Sie nicht, es der i18n-Lokalisierungsdatei hinzuzufügen, wenn die Eigenschaft „translate“ eingerichtet wurde. ?
3) Sortierreihenfolge. Dies ist die Spaltenposition im Raster. Wenn das Modul auf Magento 2 installiert wurde, das noch nie von einem Shop-Administrator verwaltet wurde, hat es Auswirkungen. Andernfalls wird unsere Spalte auf Magento 2, das verwendet wird, am Ende der Liste hinzugefügt, egal was wir tun.
4) Ausrichten. Das bedeutet, den Spalteninhalt auszurichten. Ich denke, das ist klar.
5) Datentyp. Dies ist ein Datentyp, den wir manipulieren werden. In unserem Fall ist das einfach eine Textzeile. Es kann sich jedoch um eine Liste oder einen booleschen Wert sowie um Zahlen handeln, wenn wir beispielsweise über die Produktmenge sprechen.
6) Sichtbar. Dies ist nichts anderes als die Spaltensichtbarkeit, obwohl vieles davon abhängt, ob das Raster zuvor verwendet wurde oder nicht.
Alle Daten über das Grid werden in der Magento-Datenbank in der Tabelle „ui_bookmark“ gespeichert. Wenn es also zum Zeitpunkt unserer Modulinstallation keine Aufzeichnungen über unsere Spalte für das geänderte Gitter gibt, erwarten Sie keine Wunder.
7) Filtern . Dies ist der Filtertyp. Hier haben wir angegeben, dass die Filterung wie bei normalem Text erfolgen soll. Während der Code ausgeführt wird, verwandelt er sich in die MySQL-Bedingung „LIKE %value%“.
Erläuterungen
Um es kurz zu machen, der Name der erweiterten UI-Komponente muss dem Namen des Originals entsprechen. In unserem Fall ist es „vendor/magento/module-sales/view/adminhtml/ui_component/sales_order_grid.xml“ und wird aus dem Modulstamm „view/adminhtml/ui_component/sales_order_grid.xml“ berechnet.
Das UI-Raster selbst wird dem erforderlichen Controller mithilfe des Layouts „vendor/magento/module-sales/view/adminhtml/layout/sales_order_index.xml“ wie folgt hinzugefügt:
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>
Das bedeutet *Fügen Sie diese UI-Komponente unter dem Namen `sales_order_grid` zum Seiteninhalt hinzu* ― genau wie im Fall von Blöcken. Anstelle von Blöcken haben wir jedoch `uiComponent` mit seinen Attributen und Einschränkungen.
Löschen Sie nun den Magento 2-Cache mit dem folgenden Befehl:
> sudo -u www-data php bin/magento cache:clean config
und überprüfen Sie die Ergebnisse im Auftragsraster:
3. Fügen Sie der Spalte Daten hinzu
Sie haben vielleicht bemerkt, dass die Spalte erschienen ist, aber ihr Inhalt sieht nicht so aus wie erwartet … es werden dort überhaupt keine Daten angezeigt. Fair genug, wir haben nichts hinzugefügt, daher gibt es dort keinen Inhalt.
Lassen Sie uns ein einfaches Plugin schreiben, das Ihnen beim Ausfüllen unserer Spalte helfen wird. Lassen Sie uns dazu die Grid-Sammlungsabfrage abfangen und einen Join innerhalb der erforderlichen Tabelle und des erforderlichen Grids erstellen. Das Plugin wird wie folgt aussehen:
> 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; } }
Es bezieht sich auf die folgende Klasse:
`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>
Das Plugin läuft folgendermaßen ab:
Da es absolut alle Sammlungen erfassen wird, fügen wir der erforderlichen `sales_order_grid`-Tabelle eine Validierung hinzu. Wenn es gefunden wird und Magento versucht, Daten darüber zu erhalten, verbinden wir die Tabelle mit der Adresse `sales_order_address` nach `order_id` (`entity_id` in der Tabelle `sales_order_grid` und `parent_id` in der Tabelle `sales_order_address` ( `soa` Alias)). Jetzt haben wir Zugriff auf die Adressdaten der Bestellung des Kunden, die wir verwenden können, um die „region_id“ zu bestimmen. Sie befindet sich als Zahl in der Tabelle `sales_order_address`. Diese Nummer entspricht dem Index in der Tabelle „directory_country_region“ (Alias „dcrt“). Da wir diesen Regionalcode wie oben erwähnt aus der Tabelle benötigen, schließen wir die Spalte „Code“ an. Genau diese Spalte wird ausgegeben (entspricht dem `column`-Wert in `sales_order_grid.xml`).
Dann Cache leeren:
> sudo -u www-data php bin/magento cache:clean config
Melden Sie sich im Admin-Panel beim Bestellraster an. Wenn alles richtig gemacht wurde, werden unsere Regionalcodes angezeigt:
Kostenloser Zugriff auf das Modul ist auf GitHub verfügbar: https://github.com/mageworx/articles-extended-orders-grid.
Wichtige Nebenbemerkung!
Um dieser Spalte Daten hinzuzufügen, müssen beim Erstellen einer Sammlung die Spalte „your_column_name“ und alle erforderlichen Daten hinzugefügt werden. Das heißt, Sie müssen etwas anderes tun – den Tabellennamen ersetzen und Ihren eigenen Join schreiben. Vergessen Sie auch nicht, bei Bedarf den Spaltennamen in der Datei `sales_order_grid.xml` zu bearbeiten.
Wie füge ich eine zusätzliche Spalte hinzu?
Wenn Sie sich entscheiden, eine weitere Spalte hinzuzufügen, befolgen Sie bitte die im folgenden Git-Commit beschriebenen Richtlinien: https://github.com/mageworx/articles-extended-orders-grid/commit/d31c364a25ce493ab64731c5ca0481e146dbbac3
Dort haben wir die Spalte telephone
zum Grid aus der Tabelle sales_order_address
für die Adresse der shipping
hinzugefügt. Wie Sie im Commit-Code sehen können, waren keine wesentlichen Codeänderungen erforderlich.
Darüber hinaus können diese Spalten erfolgreich aus der Standardschnittstelle „Order Grid“ exportiert werden.
So sieht das Raster mit der Spalte „Telefon“ aus:
Im folgenden Screenshot sehen Sie dieselben Bestellungen, die in eine .csv-Datei exportiert wurden:
[Aktualisieren] Wie füge ich eine Spalte mit Bestellartikelinformationen hinzu?
Wie Sie wissen, haben alle Bestellungen Stückzahlen, beginnend bei einer bis hin zu mehr als einer Zahl (ja, der Traum eines Händlers). Aber wie können wir diese Informationen im Bestellraster anzeigen, um eine Suche zu starten oder eine Analyse einfacher durchzuführen?
Wir können nicht einfach eine Spalte hinzufügen, wie wir es zuvor getan haben, da wir in diesem Fall nur einen Produktnamen oder eine SKU in jeder Zeile erhalten. Oder Auftragsdatensätze werden dupliziert … Wir brauchen dieses Durcheinander auch nicht.
Daher werde ich versuchen zu erklären, wie wir das (meiner Meinung nach) richtig machen können.
Angenommen, wir benötigen eine Datenspalte „Produktname“ im Bestellraster.
Lassen Sie uns zunächst eine neue Spalte in der sales_order_grid
Definition hinzufügen, wie wir es zuvor getan haben:
<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>
Dann müssen wir nur noch die richtige Abfrage für unsere neue Spalte erstellen. Es muss den Namen jedes Produkts enthalten, das in dieser Reihenfolge gekauft wurde, getrennt durch ein Komma, mit der Möglichkeit, nach diesen Spaltenwerten zu suchen usw. Erstellen wir eine neue Methode im Plugin 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; }
und benennen Sie diese Methode im ursprünglichen Methodenkörper:
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) { ...
Um die gewünschten Daten in einer Spalte zu erhalten, müssen wir in der Einzelauswahl eine Unterauswahl mit zwei Spalten erstellen: order_id
und name
(Produktname), die später mit der Hauptsammlung zusammengefügt werden können:
// 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');
Erläuterungen:
-
$collection->getConnection()->select()
erstellt eine neueMagento\Framework\Db\Select
-Instanz.
Dies ist erforderlich, da wir die ursprüngliche Auswahl aus der Sammlung nicht verwenden können, da sie ihre eigenen Daten enthält und alle Änderungen zu Fehlern führen. -
name
Spalte muss alle Produktnamen für die angegebene Bestellung enthalten, dh sie muss mit dem\Zend_Db_Expr('GROUP_CONCAT(DISTINCT name SEPARATOR \',\')')
gruppiert werden. Zu diesem Zweck fügen wirgroup('order_id')
später der Auswahl hinzu. Ohne Gruppierung können wir die FunktionGROUP_CONCAT
nicht verwenden.
Jetzt können wir unsere Unterauswahl zur Hauptsammlung hinzufügen und sie wird das logische Ende der Methode 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;
Erläuterungen:
-
soi
ist ein Alias für unsere Pseudotabelle. -
order_id
ist ein Schlüssel, den wir verwenden, um unsere Haupttabelle (Grid) mit den Bestellartikeldaten zu verknüpfen. -
['name']
ist die einzige Spalte, die zum Ergebnis hinzugefügt wird, da wir keine weiteren Informationen benötigen.
Das Endergebnis ist im offiziellen Repository dieses Beispiels verfügbar.
Hier ist der Link zu dem spezifischen Commit: https://github.com/mageworx/articles-extended-orders-grid/commit/0cdffcd4ba66cacb2fd857ba7626fdbcfc0d6fe3
So sieht diese Spalte auf unserem Staging-Host aus:
Und hier ist das Ergebnis des Exports (CSV):
So sieht die Abfrage aus, wenn Sie versuchen, Bestellungen mit „schwarzen“ Produkten zu suchen (auf unserem Dev-Host):
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 = 'Versand'
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
WO soi
. name
LIKE '%Black%'
Offensichtlich ist dies nicht der schnellste Weg, Daten auszugeben. Das ist aber wahrscheinlich das Einfachste. Am besten sammeln Sie Daten über Produktnamen in einer separaten Spalte einer separaten Tabelle (order_id, products_name) und fügen diese Tabelle ohne zusätzliche Gruppierung und Unterauswahl hinzu.
Dazu fügen wir unserem select (am Ende des Methodencodes) die Gruppe ('order_id') hinzu.
Die Auswahl bedeutet ein Element.
Die Gruppe bedeutet die Auswahlmethode.
Ich denke, das ist es. Sollten Sie Fragen oder Wünsche haben, hinterlassen Sie bitte einen Kommentar im Kommentarfeld.