Magento 2 Siparişler Izgarasına Filtreli Sütun Nasıl Eklenir?
Yayınlanan: 2020-02-03Sıklıkla, Magento 2 mağaza yöneticileri, siparişler ızgarasını kullanmak ve özelleştirmek söz konusu olduğunda ek seçeneklere ihtiyaç duyar ― belirli bir hazır parametreye dayalı filtreleme gerçek bir zorluk haline gelebilir.
Son zamanlarda, bir Magento Geliştiricisi bana bir soru ile ulaştı. Magento 2.3.1'deki siparişler ızgarasını genişletmeye çalıştı. Web'de bulunan eski gönderiler yardımcı olmadı - doğal olarak, son iki yıldan bu yana Magento'da çok şey değişti.
Sorusuna dayanarak, size belirli bir vakanın çözümüne bakmanızı öneriyorum:
Siparişler tablosuna bir satın alma işlemini tamamlayan bir müşterinin bölgesel kodunu içeren bir sütun eklememiz gerekiyor. Ek olarak, bir mağaza yöneticisinin bu yeni eklenen sütuna göre siparişleri filtreleme olanağı olmalıdır.
Kolay görünebilir, ancak dikkat etmeye değer birkaç şey var. Örneğin, bir satın alma işlemi yapan bir müşteri, sanal bir sipariş durumunda herhangi bir teslimat adresine sahip olmayabilir. Veya bölgeleri nasıl sıralayalım? Geliştirme aşamasına geçilirken tüm bunlar göz önünde bulundurulmalıdır. Daha önce bahsedilen sorulara dayanarak, varsayalım:
- sanal ürünlerin teslimat bölgesi ('boş') olmayacaktır. Bu, onları bu parametreye göre seçmenize yardımcı olacaktır,
- bölgeler listelenecek ve varsayılan Magento 2'de olduğu gibi, etiketlere dönüştürülmeden kodların görünümüne sahip olacaktır.
*Lütfen bu makalenin sonunda GitHub'da açık erişimli modüle bir bağlantı olacağını unutmayın. Yine de, bu makaleyi bitirmeyi başaramazsanız, bağlantıyı bu paragrafa ekliyorum: https://github.com/mageworx/articles-extended-orders-grid.
Ancak, zamanın olmamasına rağmen, okumaya devam etmenizi tavsiye ederim.?
Bu nedenle, siparişler tablosuna yeni bir sütun eklemek için yapmanız gerekenler:
İçindekiler
- 1. Yeni bir modül oluşturun
- 2. Kılavuza bir sütun ekleyin
- Açıklamalar
- 3. Sütuna veri ekleyin
- Ekstra Sütun Nasıl Eklenir?
- [Güncelleme] Sipariş Öğeleri Bilgisine Sahip Bir Sütun Nasıl Eklenir?
1. Yeni bir modül oluşturun
Öncelikle modül ve satıcı isimlerine karar verelim. Bir satıcı adı seçmeme gerek yok ― bu MageWorx (sanki bir seçeneğim varmış gibi, şaka yapıyorum). Hala modül adını seçiyorum. ExtendedOrdersGrid olsun (btw, Magento 2 için aynı ad uzantısına sahibiz). Aslında, MageWorx'ü ad alanında satıcı adı olarak kullanmak size ücretsiz destek talep etme hakkı vermez. Her neyse, destek ekibi üyelerimiz iyi bir hafta sonu geçirdiyse, yine de Pazartesi günü deneyebilirsiniz.?
Şu dizini oluşturalım: `app/code/MageWorx/ExtendedOrdersGrid`. Bir modülü kaydetmek için bazı standart dosyalara ihtiyacımız olacak:
> 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'me eklenen telif hakkını otomatik olarak kestiğimi not etmek önemlidir. Böylece bu kodu sorunsuz bir şekilde kullanabilirsiniz. ?
Ardından, birkaç komut çalıştırın:
> sudo -u www-data php bin/magento module:enable MageWorx_ExtendedOrdersGrid > sudo -u www-data php bin/magento setup:upgrade
Ve işte! Artık modülümüz Magento 2'de görülebilir! Oh, uzak bir sunucuda çalışıyorsanız, test etmeden önce dosyaları aktarmayı unutmayın.
2. Kılavuza bir sütun ekleyin
Ardından Magento 2 UI kullanarak standart ızgaraya yeni bir sütun ekleyelim. Bunun için bir dosya oluşturun:
> view/adminhtml/ui_component/sales_order_grid.xml
aşağıdaki içerikle (anlamı daha fazla tartışacağız):
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>
Burada ismin hiçbir yerden alınmadığını belirtmeniz gerekiyor. Deneyimli geliştiriciler için bu açıktır, ancak yalnızca Magento 2'yi tanıyanlar için bu paragrafın sonuna bazı açıklamalar ekleyeceğim.
Izgaraya sütun eklemek için standart bir 'sütunlar' düğümü kullandık, burada 'kod' adı altında yeni bir sütun da eklenecek. Ardından, sütunumuzun niteliklerini ızgaraya yazalım:
1) Bileşen . Bu, bu sütunun oluşturulmasından ve işlenmesinden sorumlu olan bir JS sınıfıdır. Magento_Ui modülünde aşağıdaki adreste bulunur:
'vendor/magento/module-ui/view/base/web/js/grid/columns/column.js'
Aslında, meraklı bir geliştiriciyseniz, diğer gerçekleşmelere de bir göz atın. Orada çok heyecan verici şeyler var.
2) Etiket. Bu, son kullanıcıya gösterilecek olan, sütun adına sahip bir satırdır. 'translate' özelliği kurulmuşsa, onu i18n yerelleştirme dosyasına eklemeyi unutmayın. ?
3) Sıralama. Bu, ızgaradaki sütun konumudur. Modül, Magento 2'ye daha önce bir mağaza yöneticisi tarafından yönetilmemişse kurulmuşsa, bunun bir etkisi olacaktır. Aksi takdirde, kullanılan Magento 2'de ne yaparsak yapalım sütunumuz listenin sonuna eklenecektir.
4) Hizala. Bu, sütun içeriğinin hizalanması anlamına gelir. Sanırım bu açık.
5) Veri Türü. Bu, işleyeceğimiz bir veri türüdür. Bizim durumumuzda, bu sadece bir metin satırı. Ancak, örneğin ürün miktarı hakkında konuşursak, bir liste veya Boolean değeri ve ayrıca sayılar olabilir.
6) Görünür. Bu, sütun görünürlüğünden başka bir şey değildir, ancak büyük ölçüde ızgaranın daha önce kullanılıp kullanılmadığına bağlıdır.
Izgarayla ilgili tüm veriler Magento veritabanında, ui_bookmark' tablosunda saklanır. Bu nedenle, modül kurulumumuz sırasında değiştirilen ızgara için sütunumuzla ilgili herhangi bir kayıt yoksa, herhangi bir mucize beklemeyin.
7) Filtre . Bu filtre tipidir. Burada filtrelemenin normal metinde olduğu gibi yapılması gerektiğini belirttik. Kodu çalıştırırken, MySQL `LIKE %value%` koşuluna dönüşecektir.
Açıklamalar
Uzun lafın kısası, genişletilmiş UI bileşeninin adı, orijinalin adıyla aynı olmalıdır. Bizim durumumuzda, 'vendor/magento/module-sales/view/adminhtml/ui_component/sales_order_grid.xml' şeklindedir ve 'view/adminhtml/ui_component/sales_order_grid.xml' modül kökünden hesaplanır.
UI ızgarasının kendisi, "vendor/magento/module-sales/view/adminhtml/layout/sales_order_index.xml" düzeni kullanılarak gerekli denetleyiciye aşağıdaki gibi eklenir:
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>
Bu, *bu UI bileşenini "sales_order_grid" adı altında sayfa içeriğine ekle* anlamına gelir - tıpkı bloklarda olduğu gibi. Ancak, bloklar yerine, nitelikleri ve sınırlamaları ile uiComponent'imiz var.
Şimdi, aşağıdaki komutu kullanarak Magento 2 önbelleğini temizleyin:
> sudo -u www-data php bin/magento cache:clean config
ve siparişler tablosundaki sonuçları kontrol edin:
3. Sütuna veri ekleyin
Sütunun göründüğünü fark etmiş olabilirsiniz, ancak içeriği tam olarak beklendiği gibi görünmüyor...orada hiçbir veri görüntülenmiyor. Yeterince adil, hiçbir şey eklemedik, dolayısıyla orada içerik yok.
Sütunumuzu doldurmanıza yardımcı olacak basit bir eklenti yazmaya başlayalım. Bunun için grid toplama sorgusunu yakalayalım, gerekli tablo ve grid içerisinde birleştirme yapalım. Eklenti aşağıdaki gibi görünecektir:
> 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; } }
Aşağıdaki sınıfa atıfta bulunacaktır:
`Magento\Framework\Görünüm\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>
Eklenti şu şekilde çalışır:
Kesinlikle tüm koleksiyonları yakalayacağı için gerekli `sales_order_grid` tablosuna doğrulama ekleyelim. Bulunduğunda ve Magento bununla ilgili veri elde etmeye çalıştığında, 'satış_sipariş_adresi' ile 'order_id' ('sales_order_grid' tablosunda 'entity_id' ve 'sales_order_address' tablosunda 'parent_id' ile tabloyu birleştiririz ( "soa" takma adı)). Artık, "bölge_kimliği"ni belirlemek için kullanabileceğimiz müşterinin sipariş teslimat adresi verilerine erişimimiz var. `sales_order_address` tablosunda bir sayı olarak bulunur. Bu sayı, "dizin_ülke_bölgesi" tablosundaki ("dcrt" diğer adı) dizine karşılık gelir. Tablodan bu bölge koduna ihtiyacımız olduğu için yukarıda bahsettiğimiz gibi 'code' sütununu bağlayalım. Bu kesin sütun çıktı alacaktır ("sales_order_grid.xml" içindeki "sütun" değerine karşılık gelir).
Ardından, önbelleği temizleyin:
> sudo -u www-data php bin/magento cache:clean config
Yönetici panelinde siparişler tablosuna giriş yapın. Her şey doğru yapıldıysa, bölgesel kodlarımızın görüntülendiğini göreceğiz:
Modüle ücretsiz erişim GitHub'da mevcuttur: https://github.com/mageworx/articles-extended-orders-grid.
Önemli yan not!
Bu sütuna herhangi bir veri eklemek için, bir koleksiyon oluştururken 'your_column_name' sütununun ve gerekli tüm verilerin eklenmesi gerekir. Yani, farklı bir şey yapmanız gerekiyor - tablo adını değiştirin ve kendi birleştirmenizi yazın. Ayrıca gerekirse `sales_order_grid.xml` dosyasındaki sütun adını düzenlemeyi unutmayın.
Ekstra Sütun Nasıl Eklenir?
Bir sütun daha eklemeye karar verirseniz, lütfen aşağıdaki Git taahhüdünde açıklanan yönergeleri izleyin: https://github.com/mageworx/articles-extended-orders-grid/commit/d31c364a25ce493ab64731c5ca0481e146dbbac3
Orada, shipping
türünün adresi için sales_order_address
tablosundan telephone
sütununu ızgaraya ekledik. Taahhüt kodunda görebileceğiniz gibi, önemli bir kod değişikliği gerekmedi.
Ek olarak, bu sütunlar standart 'sipariş kılavuzu' arayüzünden başarıyla dışa aktarılabilir.
'Telefon' sütunlu ızgara şöyle görünür:
Aşağıdaki ekran görüntüsünde, aynı siparişlerin bir .csv dosyasına aktarıldığını görebilirsiniz:
[Güncelleme] Sipariş Öğeleri Bilgisine Sahip Bir Sütun Nasıl Eklenir?
Bildiğiniz gibi, tüm siparişler, birden fazla sayıda (evet, tüccarların rüyası) olmak üzere, adete sahiptir. Ancak, bir arama başlatmak veya daha kolay bir analiz yapmak için bu bilgiyi siparişler tablosunda nasıl görüntüleyebiliriz?
Daha önce yaptığımız gibi yalnızca bir sütun ekleyemiyoruz çünkü bu durumda her satırda yalnızca bir ürün adı veya SKU alıyoruz. Yoksa sipariş kayıtları çoğaltılacak... Bizim de o karmaşaya ihtiyacımız yok.
Bu yüzden bunu nasıl doğru bir şekilde yapabileceğimizi açıklamaya çalışacağım (bence).
Siparişler tablosunda bir 'Ürün Adı' veri sütununa ihtiyacımız olduğunu varsayalım.
Önce, daha önce yaptığımız gibi sales_order_grid
tanımına yeni bir sütun ekleyelim:
<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>
Ardından, tek ihtiyacımız olan yeni sütunumuz için doğru sorguyu oluşturmak. Bu sırayla satın alınan her ürünün adını, virgülle ayırarak, o sütun değerlerine göre arama yapabilen vb. içermelidir. mageworx_extended_orders_grid_add_data_to_orders_grid
eklentisinde yeni bir yöntem oluşturalım:
/** * Adds products name column to the orders grid collection * * @param OrderGridCollection $collection * @return OrderGridCollection */ private function addProductsNameColumn(OrderGridCollection $collection): OrderGridCollection { return $collection; }
ve bu yöntemi orijinal yöntem gövdesi içinde adlandırın:
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) { ...
Bir sütunda istenen verileri elde etmek için, daha sonra ana koleksiyona eklenebilecek olan bireysel order_id
ve name
(ürün adı) olmak üzere iki sütunlu bir alt seçim oluşturmalıyız:
// 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');
Açıklamalar:
-
$collection->getConnection()->select()
satırı yeni birMagento\Framework\Db\Select
örneği oluşturacaktır.
Bu gereklidir, çünkü koleksiyondaki orijinal seçimi, içinde kendi verileri olduğundan ve herhangi bir değişiklik hatalara yol açacağından kullanamayız. -
name
sütunu, belirtilen sipariş için tüm ürün adlarına sahip olmalıdır, yani,\Zend_Db_Expr('GROUP_CONCAT(DISTINCT name SEPARATOR \',\')')
ifadesi kullanılarak gruplandırılmalıdır. Bu amaçla, daha sonragroup('order_id')
ekliyoruz. Gruplama olmadanGROUP_CONCAT
işlevini kullanamayız.
Artık alt seçimimizi ana koleksiyona ekleyebiliriz ve bu, addProductsNameColumn
yönteminin mantıksal sonu olacaktır:
// 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;
Açıklamalar:
-
soi
, sözde tablomuz için bir takma addır. -
order_id
, ana tablomuzu (ızgara) sipariş öğeleri verilerine bağlamak için kullandığımız bir anahtardır. -
['name']
sonuca eklenen tek sütundur, çünkü başka bilgilere ihtiyacımız yoktur.
Nihai sonuç, bu örneğin resmi deposunda mevcuttur.
İşte belirli taahhüdün bağlantısı: https://github.com/mageworx/articles-extended-orders-grid/commit/0cdffcd4ba66cacb2fd857ba7626fdbcfc0d6fe3
Bu sütun, hazırlama sunucumuzda şöyle görünür:
Ve işte dışa aktarmanın sonucu (CSV):
"Siyah" ürünlerle (geliştirici ana makinemizde) siparişleri aramaya çalışırken sorgunun nasıl göründüğü aşağıda açıklanmıştır:
SELECT main_table
.*, soat
. telephone
, dcrt
. code
, soi
. name
FROM sales_order_grid
AS main_table
soat
ON SOAT.parent_id = main_table.entity_id AND soat.address_type = 'shipping' OLARAK sales_order_address
JOIN JOIN
LEFT JOIN directory_country_region
dcrt
ON soat.region_id = dcrt.region_id
LEFT JOIN (SELECT GROUP_CONCAT(DISTINCT name SEPARATOR ',') name
, sales_order_item
. order_id
sales_order_item
GROUP BY order_id
) AS soi
ON soi.order_id = main_table.entity_id
NEREDE soi
. name
GİBİ '%Black%'
Açıkçası, bu veri çıktısı almanın en hızlı yolu değil. Ancak, muhtemelen en kolayı bu. En iyi yol, ürün adlarıyla ilgili verileri ayrı bir tablonun (sipariş_kimliği, ürünler_adı) ayrı bir sütununda toplamak ve bu tabloyu fazladan gruplandırma ve herhangi bir alt seçim yapmadan eklemektir.
Bu amaçla grubu ('order_id') seçimimize ekliyoruz (yöntem kodunun sonunda).
Seçim, bir öğe anlamına gelir.
Grup, seçme yöntemi anlamına gelir.
Sanırım bu kadar. Herhangi bir sorunuz veya isteğiniz varsa, lütfen yorum alanına bir yorum bırakın.