Cum să adăugați o coloană cu filtru la Grila de comenzi Magento 2?

Publicat: 2020-02-03

Adesea, administratorii magazinelor Magento 2 au nevoie de opțiuni suplimentare atunci când vine vorba de utilizarea și personalizarea grilei de comenzi – filtrarea bazată pe un parametru specific disponibil poate deveni o adevărată provocare.

Recent, un dezvoltator Magento m-a contactat cu o întrebare. A încercat să extindă grila de comenzi pe Magento 2.3.1. Postările vechi disponibile pe web nu au ajutat - desigur, multe s-au schimbat în Magento din ultimii doi ani.

Pe baza întrebării sale, vă propun să vă uitați la soluția pentru un caz specific:

Trebuie să adăugăm o coloană ― cu un cod regional al unui client care a finalizat o achiziție ― la grila de comenzi. În plus, un administrator de magazin trebuie să aibă posibilitatea de a filtra comenzile după această coloană nou adăugată.

Poate părea ușor, dar există câteva lucruri la care merită să fii atent. De exemplu, un cumpărător care a făcut o achiziție poate să nu aibă nicio adresă de livrare - în cazul unei comenzi virtuale. Sau, cum vom enumera regiunile? Toate acestea ar trebui luate în considerare atunci când trecem la dezvoltare. Pe baza întrebărilor menționate mai devreme, să presupunem:

  • produsele virtuale nu vor avea o regiune de livrare („null”). Acest lucru vă va ajuta să le alegeți pe baza acestui parametru,
  • regiunile vor fi listate și vor avea o privire de coduri fără transformarea lor în etichete, așa cum este în Magento 2 implicit.

*Vă rugăm să rețineți că la sfârșitul acestui articol va exista un link către modulul cu acces deschis pe GitHub. Cu toate acestea, includ linkul în acest paragraf dacă nu reușiți să finalizați acest articol: https://github.com/mageworx/articles-extended-orders-grid.

Cu toate acestea, în ciuda lipsei de timp, vă încurajez să citiți mai departe.?

Astfel, pentru a adăuga o nouă coloană la grila de comenzi, trebuie să:

Cuprins

  • 1. Creați un modul nou
  • 2. Adăugați o coloană la grilă
    • Explicații
  • 3. Adăugați date în coloană
  • Cum să adăugați o coloană suplimentară?
  • [Actualizare] Cum să adăugați o coloană cu informații despre articolele de comandă?

1. Creați un modul nou

Mai întâi, să decidem cu privire la modulul și numele furnizorilor. Ei bine, nu este nevoie să aleg un nume de furnizor – este MageWorx (de parcă aș avea de ales, glumesc). Încă pot să aleg numele modulului. Lasă-l să fie ExtendedOrdersGrid (dar avem o extensie cu același nume pentru Magento 2). De fapt, utilizarea MageWorx ca nume de furnizor în spațiul de nume nu vă oferă dreptul de a solicita asistență gratuită. Oricum, dacă membrii echipei noastre de asistență au avut un weekend bun, puteți încerca totuși luni.?

Să creăm următorul director: `app/code/MageWorx/ExtendedOrdersGrid`. Pentru a înregistra un modul, vom avea nevoie de câteva fișiere 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>

Este important să rețineți că am tăiat automat drepturile de autor care sunt adăugate în IDE-ul meu. Astfel, puteți utiliza acest cod fără probleme. ?

Apoi, executați câteva comenzi:

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

Și voila! Acum, modulul nostru poate fi văzut în Magento 2! Oh, dacă lucrați pe un server la distanță, nu uitați să transferați fișierele înainte de a testa.

2. Adăugați o coloană la grilă

Apoi, folosind Magento 2 UI, să adăugăm o nouă coloană la grila standard. Pentru asta, creați un fișier:

 > view/adminhtml/ui_component/sales_order_grid.xml

cu următorul conținut (sensul său îl vom discuta în continuare):

 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>

Aici, trebuie să specificați că numele nu este scos de nicăieri. Pentru dezvoltatorii experimentați, acest lucru este clar, dar pentru cei care nu cunosc decât Magento 2, voi adăuga câteva explicații la sfârșitul acestui paragraf.

Am folosit un nod standard „coloane” pentru a adăuga coloane la grilă, unde va fi adăugată și o nouă coloană sub numele „cod”. În continuare, să scriem atributele coloanei noastre în grilă:

1) Componentă . Aceasta este o clasă JS care este responsabilă pentru crearea și procesarea acestei coloane. Se află în modulul Magento_Ui la următoarea adresă:

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

De fapt, dacă ești un dezvoltator curios, aruncă o privire și la alte realizări. Există o mulțime de lucruri interesante.

2) Etichetă. Aceasta este o linie cu un nume de coloană, care va fi afișată unui utilizator final. Nu uitați să îl adăugați în fișierul de localizare i18n, dacă proprietatea `translate` a fost stabilită. ?

3) SortOrder. Aceasta este poziția coloanei în grilă. Dacă modulul a fost instalat pe Magento 2 care nu a fost niciodată gestionat de un administrator al magazinului, acesta va avea efect. În caz contrar, pe Magento 2 care este utilizat, coloana noastră va fi adăugată la sfârșitul listei, indiferent de ceea ce facem.

4) Aliniați. Aceasta înseamnă alinierea conținutului coloanei. Presupun că e clar.

5) DataType. Acesta este un tip de date pe care îl vom manipula. În cazul nostru, aceasta este pur și simplu o linie de text. Cu toate acestea, poate fi o listă sau o valoare booleană, precum și numere dacă vorbim despre cantitatea produselor, de exemplu.

6) Vizibil. Aceasta nu este altceva decât vizibilitatea coloanei, deși mult depinde dacă grila a fost folosită anterior sau nu.

Toate datele despre grilă sunt stocate în baza de date Magento, în tabelul `ui_bookmark`. Astfel, dacă nu există nicio înregistrare despre coloana noastră pentru grila modificată în momentul instalării modulului nostru, nu vă așteptați la niciun miracol.

7) Filtru . Acesta este tipul de filtru. Aici, am specificat că filtrarea trebuie făcută ca și în cazul textului obișnuit. În timpul rulării codului, acesta se va transforma în condiția MySQL `LIKE %value%`.


Extensiile MageWorx Magento 2

Explicații

Pentru a scurta povestea lungă, numele componentei UI extinsă trebuie să corespundă cu numele originalului. În cazul nostru, este `vendor/magento/module-sales/view/adminhtml/ui_component/sales_order_grid.xml` și este calculat din rădăcina modulului `view/adminhtml/ui_component/sales_order_grid.xml`.

Grila UI în sine este adăugată la controlerul necesar folosind aspectul „vendor/magento/module-sales/view/adminhtml/layout/sales_order_index.xml” după cum urmează:

 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>

Aceasta înseamnă *adăugați această componentă UI sub numele `sales_order_grid` la conținutul paginii* ― la fel ca în cazul blocurilor. Cu toate acestea, în loc de blocuri, avem `uiComponent` cu atributele și limitările sale.


Acum, ștergeți memoria cache Magento 2 folosind următoarea comandă:

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

și verificați rezultatele în grila de comenzi:

Cum să adăugați o coloană cu filtru la Grila de comenzi Magento 2? | MageWorx Magento Blog

3. Adăugați date în coloană

S-ar putea să fi observat că coloana a apărut, dar conținutul ei nu arată așa cum era de așteptat... nu există deloc date afișate acolo. Destul de corect, nu am adăugat nimic, deci nici conținut acolo.

Să trecem la a scrie un plugin simplu care vă va ajuta să completați coloana noastră. Pentru asta, să prindem interogarea de colecție grilă, să facem o îmbinare în tabelul și grila necesare. Pluginul va arăta după cum urmează:

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

Se va referi la următoarea clasă:

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

Pluginul rulează în felul următor:

Deoarece va prinde absolut toate colecțiile, să adăugăm validarea tabelului necesar `sales_order_grid`. Când este găsit și Magento încearcă să obțină date despre aceasta, facem o îmbinare a tabelului cu adresa `sales_order_address` prin`order_id` (`entity_id` în tabelul `sales_order_grid` și `parent_id` în tabelul `sales_order_address`) ( `soa` alias)). Acum, avem acces la datele despre adresa de livrare a comenzii ale clientului, pe care le putem folosi pentru a determina „region_id”. Este situat ca număr în tabelul „adresă_comandă_vânzări”. Acest număr corespunde indexului din tabelul `directory_country_region` (alias `dcrt`). Deoarece avem nevoie de acest cod regional din tabelul menționat mai sus, să conectăm coloana „cod”. Această coloană precisă va primi rezultate (corespunde valorii „coloană” din „sales_order_grid.xml”).

Apoi, goliți memoria cache:

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

Conectați-vă în panoul de administrare la grila de comenzi. Dacă totul a fost făcut corect, vom vedea codurile noastre regionale afișate:

Cum să adăugați o coloană cu filtru la Grila de comenzi Magento 2? | MageWorx Magento Blog

Accesul gratuit la modul este disponibil pe GitHub: https://github.com/mageworx/articles-extended-orders-grid.

Notă importantă!

Pentru a adăuga date la această coloană, este necesar să obțineți coloana „your_column_name” și toate datele necesare adăugate la crearea unei colecții. Adică, trebuie să faceți ceva diferit - înlocuiți numele tabelului și scrieți propria dvs. unire. De asemenea, nu uitați să editați numele coloanei în fișierul `sales_order_grid.xml`, dacă este necesar.

Cum să adăugați o coloană suplimentară?

Dacă decideți să adăugați încă o coloană, vă rugăm să urmați instrucțiunile descrise în următorul commit Git: https://github.com/mageworx/articles-extended-orders-grid/commit/d31c364a25ce493ab64731c5ca0481e146dbbac3

Acolo, am adăugat coloana de telephone la grila din tabelul sales_order_address pentru adresa tipului de shipping . După cum puteți vedea în codul de comitere, nu au fost necesare modificări semnificative ale codului.

În plus, aceste coloane pot fi exportate cu succes din interfața standard „grilă de comandă”.

Iată cum arată grila cu coloana „telefon”:

Cum să adăugați o coloană cu filtru la Grila de comenzi Magento 2? | MageWorx Magento Blog

În captura de ecran de mai jos, puteți vedea aceleași comenzi exportate într-un fișier .csv:

Cum să adăugați o coloană cu filtru la Grila de comenzi Magento 2? | MageWorx Magento Blog

[Actualizare] Cum să adăugați o coloană cu informații despre articolele de comandă?

După cum știți, toate comenzile au o cantitate de articole, începând de la unu până la dincolo de număr (da, visul comercianților). Dar cum putem afișa aceste informații în grila de comenzi pentru a începe o căutare sau a efectua o analiză mai ușor?

Nu putem adăuga doar o coloană, așa cum am făcut-o mai devreme, deoarece primim doar un nume de produs sau SKU pe fiecare rând în acest caz. Sau, înregistrările comenzilor vor fi duplicate... Nici nu avem nevoie de această mizerie.

Astfel, voi încerca să explic cum putem face asta în mod corect (în opinia mea).

Să presupunem că avem nevoie de o coloană de date „Nume produs” în grila de comenzi.

Mai întâi, să adăugăm o nouă coloană în definiția sales_order_grid , așa cum am făcut-o mai devreme:

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

Apoi, tot ce ne trebuie este să construim interogarea potrivită pentru noua noastră coloană. Trebuie să conțină numele fiecărui produs cumpărat în acea ordine, despărțit prin virgulă, cu posibilitatea de a căuta după valorile acelei coloane etc. Să creăm o nouă metodă în plugin-ul 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; }

și denumește acea metodă în corpul metodei inițiale:

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

Pentru a obține datele dorite într-o singură coloană, trebuie să creăm o sub-selectare cu două coloane: order_id și name (nume produs) în selectarea individuală, care poate fi alăturată ulterior colecției principale:

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

Clarificări:

  • $collection->getConnection()->select() line va crea o nouă instanță Magento\Framework\Db\Select .
    Acest lucru este necesar deoarece nu putem folosi selecția originală din colecție, deoarece are propriile sale date în interior și orice modificare va duce la erori.
  • Coloana name trebuie să aibă toate numele produselor pentru comanda specificată, adică trebuie grupată folosind expresia \Zend_Db_Expr('GROUP_CONCAT(DISTINCT name SEPARATOR \',\')') . În acest scop, adăugăm group('order_id') la selectare mai târziu. Fără grupare, nu putem folosi funcția GROUP_CONCAT .

Acum, putem adăuga sub-selectarea noastră la colecția principală și va fi sfârșitul logic al metodei 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;

Clarificări:

  • soi este un alias pentru pseudo-tabelul nostru.
  • order_id este o cheie, pe care o folosim pentru a lega tabelul nostru principal (grila) la datele articolelor de comandă.
  • ['name'] este singura coloană, care se adaugă la rezultat, deoarece nu avem nevoie de alte informații.

Rezultatul final este disponibil în depozitul oficial al exemplului respectiv.
Iată linkul către commit-ul specific: https://github.com/mageworx/articles-extended-orders-grid/commit/0cdffcd4ba66cacb2fd857ba7626fdbcfc0d6fe3

Iată cum arată acea coloană pe gazda noastră de pregătire:

?? Cum să adăugați o coloană cu filtru la Grila de comenzi Magento 2? | MageWorx Magento Blog

Și iată rezultatul exportului (CSV):

Și iată rezultatul exportului (CSV):

Iată cum arată interogarea când încercați să căutați comenzi cu produse „Negru” (pe gazda noastră de dezvoltare):
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 = „livrare”
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
UNDE soi . name LIKE '%Black%'

Evident, acesta nu este cel mai rapid mod de a scoate date. Cu toate acestea, acesta este probabil cel mai ușor. Cel mai bun mod este să acumulați date despre numele produselor într-o coloană separată a unui tabel separat (codul_comandă, numele_produselor) și să adăugați acest tabel fără grupări suplimentare și nicio sub-selecție.

În acest scop, adăugăm grupul ('order_id') la selecția noastră (la sfârșitul codului metodei).
Selectarea înseamnă un element.
Grupul înseamnă metoda selectată.


Presupun că asta este. Dacă aveți întrebări sau solicitări, vă rugăm să lăsați un comentariu în câmpul de comentarii.