Come aggiungere una colonna con filtro alla griglia degli ordini di Magento 2?

Pubblicato: 2020-02-03

Spesso, gli amministratori dei negozi Magento 2 richiedono opzioni aggiuntive quando si tratta di utilizzare e personalizzare la griglia degli ordini: il filtraggio in base a un parametro specifico pronto all'uso può diventare una vera sfida.

Di recente, uno sviluppatore Magento mi ha contattato con una domanda. Ha provato ad espandere la griglia degli ordini su Magento 2.3.1. I vecchi post disponibili sul web non hanno aiutato – naturalmente, molto è cambiato in Magento negli ultimi due anni.

Sulla base della sua domanda, ti offro di dare un'occhiata alla soluzione per un caso specifico:

È necessario aggiungere una colonna ― con un codice regionale di un cliente che ha completato un acquisto ― alla griglia degli ordini. Inoltre, un amministratore del negozio deve avere la possibilità di filtrare gli ordini in base a questa colonna appena aggiunta.

Potrebbe sembrare facile, ma ci sono un paio di cose a cui vale la pena prestare attenzione. Ad esempio, un acquirente che ha effettuato un acquisto potrebbe non avere alcun indirizzo di consegna ― nel caso di un ordine virtuale. Oppure, come elenchiamo le regioni? Tutto questo dovrebbe essere preso in considerazione quando si passa allo sviluppo. Sulla base delle domande menzionate in precedenza, assumiamo:

  • i prodotti virtuali non avranno una regione di consegna ("null"). Questo ti aiuterà a sceglierli in base a questo parametro,
  • le regioni verranno elencate e avranno un'occhiata ai codici senza la loro trasformazione in etichette, proprio come nel Magento 2 predefinito.

*Si noti che alla fine di questo articolo ci sarà un collegamento al modulo con accesso aperto su GitHub. Tuttavia, includo il collegamento in questo paragrafo se non riesci a finire questo articolo: https://github.com/mageworx/articles-extended-orders-grid.

Tuttavia, nonostante la mancanza di tempo, ti incoraggio a continuare a leggere.?

Pertanto, per aggiungere una nuova colonna alla griglia degli ordini, è necessario:

Sommario

  • 1. Crea un nuovo modulo
  • 2. Aggiungi una colonna alla griglia
    • Spiegazioni
  • 3. Aggiungi i dati alla colonna
  • Come aggiungere una colonna extra?
  • [Aggiorna] Come aggiungere una colonna con le informazioni sugli articoli dell'ordine?

1. Crea un nuovo modulo

Innanzitutto, decidiamo il modulo e i nomi dei fornitori. Bene, non c'è bisogno che io scelga il nome di un venditore – è MageWorx (come se avessi una scelta, sto scherzando). Posso ancora scegliere il nome del modulo. Lascia che sia ExtendedOrdersGrid (tra l'altro abbiamo un'estensione con lo stesso nome per Magento 2). In effetti, l'utilizzo di MageWorx come nome del venditore nello spazio dei nomi non ti dà il diritto di richiedere supporto gratuito. Ad ogni modo, se i membri del nostro team di supporto hanno trascorso un buon fine settimana, puoi comunque provarlo lunedì.?

Creiamo la seguente directory: `app/code/MageWorx/ExtendedOrdersGrid`. Per registrare un modulo, avremo bisogno di alcuni file standard:

 > 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>

È importante notare che ho tagliato il copyright che viene aggiunto automaticamente al mio IDE. Pertanto, puoi utilizzare questo codice senza problemi. ?

Quindi, esegui alcuni comandi:

 > sudo -u www-data php bin/magento module:enable MageWorx_ExtendedOrdersGrid > sudo -u www-data php bin/magento setup:upgrade

E voilà! Ora, il nostro modulo può essere visto in Magento 2! Oh, se lavori su un server remoto, non dimenticare di trasferire i file prima del test.

2. Aggiungi una colonna alla griglia

Quindi, utilizzando l'interfaccia utente di Magento 2, aggiungiamo una nuova colonna alla griglia standard. Per questo, crea un file:

 > view/adminhtml/ui_component/sales_order_grid.xml

con il seguente contenuto (di cui parleremo ulteriormente):

 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>

Qui, è necessario specificare che il nome non viene tolto da nessuna parte. Per gli sviluppatori esperti, questo è chiaro, ma per coloro che conoscono solo Magento 2, aggiungerò alcune spiegazioni alla fine di questo paragrafo.

Abbiamo usato un nodo "colonne" standard per aggiungere colonne alla griglia, dove verrà aggiunta anche una nuova colonna sotto il nome "codice". Quindi, scriviamo gli attributi della nostra colonna nella griglia:

1) Componente . Questa è una classe JS responsabile della creazione e dell'elaborazione di questa colonna. Si trova nel modulo Magento_Ui al seguente indirizzo:

`vendor/magento/module-ui/view/base/web/js/grid/columns/column.js`

Infatti, se sei uno sviluppatore curioso, dai un'occhiata anche ad altre realizzazioni. Ci sono un sacco di cose eccitanti là fuori.

2) Etichetta. Questa è una riga con un nome di colonna, che verrà visualizzata a un utente finale. Non dimenticare di aggiungerlo al file di localizzazione di i18n, se è stata stabilita la proprietà `translate`. ?

3) Ordina. Questa è la posizione della colonna nella griglia. Se il modulo è stato installato su Magento 2 che non è mai stato gestito da un amministratore del negozio, avrà effetto. Altrimenti, su Magento 2 in uso, la nostra colonna verrà aggiunta alla fine dell'elenco, indipendentemente da ciò che facciamo.

4) Allinea. Ciò significa allineare il contenuto della colonna. Immagino sia chiaro.

5) Tipo di dati. Questo è un tipo di dati che manipoleremo. Nel nostro caso, è semplicemente una riga di testo. Tuttavia, può essere un elenco o un valore booleano, oltre a numeri se parliamo, ad esempio, della quantità di prodotti.

6) Visibile. Questo non è altro che la visibilità della colonna, anche se molto dipende dal fatto che la griglia sia stata utilizzata in precedenza o meno.

Tutti i dati sulla griglia sono archiviati nel database Magento, nella tabella `ui_bookmark`. Quindi, se non c'è traccia della nostra colonna per la griglia modificata al momento dell'installazione del nostro modulo, non aspettarti alcun miracolo.

7) Filtro . Questo è il tipo di filtro. Qui, abbiamo specificato che il filtraggio dovrebbe essere eseguito come con il testo normale. Durante l'esecuzione del codice, si trasformerà nella condizione MySQL `LIKE %value%`.


Estensioni MageWorx Magento 2

Spiegazioni

Per farla breve, il nome del componente dell'interfaccia utente estesa deve corrispondere al nome dell'originale. Nel nostro caso, è `vendor/magento/module-sales/view/adminhtml/ui_component/sales_order_grid.xml`, ed è calcolato dalla radice del modulo `view/adminhtml/ui_component/sales_order_grid.xml`.

La stessa griglia dell'interfaccia utente viene aggiunta al controller richiesto utilizzando il layout `vendor/magento/module-sales/view/adminhtml/layout/sales_order_index.xml` proprio come segue:

 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>

Ciò significa *aggiungere questo componente dell'interfaccia utente sotto il nome `sales_order_grid` al contenuto della pagina* ― proprio come in caso di blocchi. Tuttavia, invece dei blocchi, abbiamo 'uiComponent' con i suoi attributi e limitazioni.


Ora, svuota la cache di Magento 2 usando il seguente comando:

 > sudo -u www-data php bin/magento cache:clean config

e controlla i risultati nella griglia degli ordini:

Come aggiungere una colonna con filtro alla griglia degli ordini di Magento 2? | Blog MageWorx Magento

3. Aggiungi i dati alla colonna

Potresti aver notato che la colonna è apparsa, ma il suo contenuto non sembra proprio come previsto... non ci sono dati visualizzati lì. Abbastanza giusto, non abbiamo aggiunto nulla, quindi nessun contenuto lì.

Passiamo a scrivere un semplice plugin che ti aiuterà a riempire la nostra colonna. Per questo, prendiamo la query di raccolta della griglia, creiamo un join all'interno della tabella e della griglia richieste. Il plugin avrà il seguente aspetto:

 > 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; } }

Si riferirà alla classe seguente:

`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>

Il plugin funziona nel modo seguente:

Poiché catturerà assolutamente tutte le raccolte, aggiungiamo la convalida alla tabella `sales_order_grid` richiesta. Quando viene trovato e Magento tenta di ottenere dati su questo, eseguiamo un join della tabella con l'indirizzo `sales_order_address` tramite `order_id` (`entity_id` nella tabella `sales_order_grid` e `parent_id` nella tabella `sales_order_address` ( `soa` alias)). Ora abbiamo accesso ai dati dell'indirizzo di consegna dell'ordine del cliente, che possiamo utilizzare per determinare `region_id`. Si trova come un numero nella tabella `sales_order_address`. Questo numero corrisponde all'indice nella tabella `directory_country_region` (alias `dcrt`). Poiché abbiamo bisogno di questo codice regionale dalla tabella come menzionato sopra, colleghiamo la colonna "codice". Questa colonna precisa otterrà un output (corrisponde al valore di `colonna` in `sales_order_grid.xml`).

Quindi, svuota la cache:

 > sudo -u www-data php bin/magento cache:clean config

Accedi dal pannello di amministrazione alla griglia degli ordini. Se tutto è stato fatto correttamente, vedremo visualizzati i nostri codici regionali:

Come aggiungere una colonna con filtro alla griglia degli ordini di Magento 2? | Blog MageWorx Magento

L'accesso gratuito al modulo è disponibile su GitHub: https://github.com/mageworx/articles-extended-orders-grid.

Nota importante!

Per aggiungere dati a questa colonna, è necessario ottenere la colonna "nome_colonna" e tutti i dati necessari aggiunti durante la creazione di una raccolta. Cioè, devi fare qualcosa di diverso: sostituire il nome della tabella e scrivere il tuo join. Inoltre, non dimenticare di modificare il nome della colonna nel file `sales_order_grid.xml`, se necessario.

Come aggiungere una colonna extra?

Se decidi di aggiungere un'altra colonna, segui le linee guida descritte nel seguente Git commit: https://github.com/mageworx/articles-extended-orders-grid/commit/d31c364a25ce493ab64731c5ca0481e146dbbac3

Lì, abbiamo aggiunto la colonna del telephone alla griglia dalla tabella sales_order_address per l'indirizzo del tipo di shipping . Come puoi vedere nel codice di commit, non sono state richieste modifiche significative al codice.

Inoltre, queste colonne possono essere esportate con successo dall'interfaccia standard della "griglia degli ordini".

Ecco come appare la griglia con la colonna "telefono":

Come aggiungere una colonna con filtro alla griglia degli ordini di Magento 2? | Blog MageWorx Magento

Nello screenshot qui sotto, puoi vedere gli stessi ordini esportati in un file .csv:

Come aggiungere una colonna con filtro alla griglia degli ordini di Magento 2? | Blog MageWorx Magento

[Aggiorna] Come aggiungere una colonna con le informazioni sugli articoli dell'ordine?

Come sai, tutti gli ordini hanno una quantità di articoli, a partire da uno fino a oltre il numero (sì, il sogno dei commercianti). Ma come possiamo visualizzare queste informazioni nella griglia degli ordini per avviare una ricerca o eseguire un'analisi più facilmente?

Non possiamo semplicemente aggiungere una colonna come abbiamo fatto in precedenza perché in tal caso otteniamo un solo nome di prodotto o SKU su ogni riga. Oppure, i record degli ordini verranno duplicati... Non abbiamo nemmeno bisogno di quel pasticcio.

Quindi, cercherò di spiegare come possiamo farlo nel modo giusto (secondo me).

Supponiamo di aver bisogno di una colonna di dati "Nome prodotto" nella griglia degli ordini.

Innanzitutto, aggiungiamo una nuova colonna nella definizione sales_order_grid , come abbiamo fatto in precedenza:

 <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>

Quindi, tutto ciò di cui abbiamo bisogno è creare la query giusta per la nostra nuova colonna. Deve contenere il nome di ogni prodotto acquistato in quell'ordine, separato da una virgola, con la possibilità di cercare in base ai valori di quella colonna, ecc. Creiamo un nuovo metodo nel 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; }

e nomina quel metodo all'interno del corpo del metodo originale:

 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) { ...

Per ottenere i dati desiderati in una colonna, dobbiamo creare una sottoselezione con due colonne: order_id e name (nome prodotto) nella selezione individuale, che può essere unita alla raccolta principale in seguito:

 // 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');

Chiarimenti:

  • La riga $collection->getConnection()->select() creerà una nuova istanza Magento\Framework\Db\Select .
    Ciò è necessario perché non possiamo utilizzare la selezione originale dalla raccolta poiché contiene i propri dati e qualsiasi modifica comporterà errori.
  • la colonna del name deve contenere tutti i nomi dei prodotti per l'ordine specificato, ovvero deve essere raggruppata utilizzando l' \Zend_Db_Expr('GROUP_CONCAT(DISTINCT name SEPARATOR \',\')') . A tale scopo, aggiungeremo group('order_id') alla selezione in un secondo momento. Senza raggruppamento, non possiamo utilizzare la funzione GROUP_CONCAT .

Ora possiamo aggiungere la nostra selezione secondaria alla raccolta principale e sarà la fine logica del metodo 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;

Chiarimenti:

  • soi è un alias per la nostra pseudo-tabella.
  • order_id è una chiave, che utilizziamo per collegare la nostra tabella principale (griglia) ai dati degli articoli dell'ordine.
  • ['name'] è l'unica colonna che viene aggiunta al risultato, perché non abbiamo bisogno di altre informazioni.

Il risultato finale è disponibile nel repository ufficiale di quell'esempio.
Ecco il link al commit specifico: https://github.com/mageworx/articles-extended-orders-grid/commit/0cdffcd4ba66cacb2fd857ba7626fdbcfc0d6fe3

Ecco come appare quella colonna sul nostro host di staging:

?‍? Come aggiungere una colonna con filtro alla griglia degli ordini di Magento 2? | Blog MageWorx Magento

Ed ecco il risultato dell'export (CSV):

Ed ecco il risultato dell'export (CSV):

Ecco come appare la query quando si tenta di cercare ordini con prodotti "Black" (sul nostro host di sviluppo):
SELEZIONA main_table .*, soat . telephone , dcrt . code , soi . name FROM sales_order_grid AS main_table
SINISTRA ISCRIVITI sales_order_address AS soat ON soat.parent_id = main_table.entity_id AND soat.address_type = 'spedizione'
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
DOVE soi . name MI PIACE '%Black%'

Evidentemente, questo non è il modo più veloce per produrre dati. Tuttavia, questo è probabilmente il più semplice. Il modo migliore è accumulare dati sui nomi dei prodotti in una colonna separata di una tabella separata (order_id, product_name) e aggiungere questa tabella senza raggruppamenti aggiuntivi e sottoselezione.

A tale scopo, aggiungiamo il gruppo ("order_id") alla nostra selezione (alla fine del codice del metodo).
La selezione indica un elemento.
Il gruppo indica il metodo di selezione.


Immagino che sia tutto. In caso di domande o richieste, si prega di lasciare un commento nel campo dei commenti.