كيفية إضافة عمود مع مرشح لشبكة أوامر Magento 2؟
نشرت: 2020-02-03في كثير من الأحيان ، يحتاج مديرو متاجر Magento 2 إلى خيارات إضافية عندما يتعلق الأمر باستخدام شبكة الطلبات وتخصيصها - يمكن أن تصبح التصفية استنادًا إلى معلمة خارج الصندوق تحديًا حقيقيًا.
في الآونة الأخيرة ، تواصل معي أحد مطوري Magento بسؤال. حاول توسيع شبكة الطلبات على Magento 2.3.1. لم تساعد المنشورات القديمة المتوفرة على الويب - بطبيعة الحال ، لقد تغير الكثير في Magento منذ العامين الماضيين.
وبناءً على سؤاله ، أعرض عليكم النظر في الحل لحالة معينة:
نحتاج إلى إضافة عمود - مع بعض الرموز الإقليمية للعميل الذي أكمل عملية شراء - إلى شبكة الطلبات. بالإضافة إلى ذلك ، يجب أن يكون لدى مسؤول المتجر إمكانية تصفية الطلبات حسب هذا العمود المضاف حديثًا.
قد يبدو الأمر سهلاً ، ولكن هناك أمران يستحقان الاهتمام بهما. على سبيل المثال ، قد لا يكون لدى المتسوق الذي أجرى عملية شراء أي عنوان تسليم - في حالة وجود طلب افتراضي. أو كيف نسرد المناطق؟ كل هذا يجب أن يؤخذ في الاعتبار عند الشروع في التنمية. بناءً على الأسئلة المذكورة سابقًا ، لنفترض:
- لن تحتوي المنتجات الافتراضية على منطقة تسليم ("فارغة"). سيساعدك هذا في اختيارهم بناءً على هذه المعلمة ،
- سيتم سرد المناطق وإلقاء نظرة على الرموز دون تحويلها إلى تسميات ، تمامًا كما هو الحال في 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 ، سأضيف بعض التفسيرات في نهاية هذه الفقرة.
استخدمنا عقدة "أعمدة" قياسية لإضافة أعمدة إلى الشبكة ، حيث تتم إضافة عمود جديد تحت اسم "الكود" أيضًا. بعد ذلك ، دعنا نكتب سمات العمود في الشبكة:
1) المكون . هذه فئة JS مسؤولة عن إنشاء هذا العمود ومعالجته. يقع في وحدة Magento_Ui على العنوان التالي:
`بائع / ماجنتو / وحدة واجهة مستخدم / عرض / قاعدة / ويب / js / شبكة / أعمدة / عمود. js`
في الواقع ، إذا كنت مطورًا فضوليًا ، فقم بإلقاء نظرة على الإنجازات الأخرى أيضًا. هناك الكثير من الأشياء المثيرة هناك.
2) التسمية. هذا سطر باسم عمود ، والذي سيتم عرضه للمستخدم النهائي. لا تنس إضافته إلى ملف الترجمة i18n ، إذا تم إنشاء خاصية "translate". ؟
3) الترتيب. هذا هو موضع العمود في الشبكة. إذا تم تثبيت الوحدة على Magento 2 التي لم تتم إدارتها من قبل مسؤول المتجر ، فسيكون لها تأثير. خلاف ذلك ، في Magento 2 المستخدمة ، ستتم إضافة عمودنا إلى نهاية القائمة بغض النظر عما نفعله.
4) محاذاة. هذا يعني محاذاة محتوى العمود. أعتقد أن هذا واضح.
5) نوع البيانات. هذا هو نوع البيانات الذي سنتعامل معه. في حالتنا ، هذا مجرد سطر من النص. ومع ذلك ، يمكن أن تكون قائمة أو قيمة منطقية ، بالإضافة إلى أرقام إذا تحدثنا عن كمية المنتجات ، على سبيل المثال.
6) مرئي. هذا ليس سوى رؤية العمود على الرغم من أن الكثير يعتمد على ما إذا كانت الشبكة قد تم استخدامها مسبقًا أم لا.
يتم تخزين جميع البيانات المتعلقة بالشبكة في قاعدة بيانات Magento ، في جدول "ui_bookmark". وبالتالي ، إذا لم يكن هناك سجل حول عمود الشبكة المعدلة في وقت تثبيت الوحدة الخاصة بنا ، فلا تتوقع أي معجزة.
7) مرشح . هذا هو نوع المرشح. هنا ، حددنا أن التصفية يجب أن تتم كما هو الحال مع النص العادي. أثناء تشغيل الكود ، سيتحول إلى حالة MySQL `` LIKE٪ value٪ ``.
تفسيرات
لجعل القصة الطويلة قصيرة ، يجب أن يتوافق اسم مكون واجهة المستخدم الممتد مع اسم الأصل. في حالتنا ، هو `vendor / magento / module-sales / view / adminhtml / ui_component / sales_order_grid.xml` ، ويتم حسابه من جذر الوحدة النمطية` view / adminhtml / ui_component / sales_order_grid.xml`.
تتم إضافة شبكة واجهة المستخدم نفسها إلى وحدة التحكم المطلوبة باستخدام تخطيط `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` إلى محتوى الصفحة * - تمامًا كما في حالة الكتل. ومع ذلك ، بدلاً من الكتل ، لدينا "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 الحصول على بيانات حول هذا الأمر ، فإننا نقوم بربط الجدول بعنوان "عنوان_العنوان_المبيعات" من خلال "معرف_الطلب" ("معرف_الكيان" في جدول "ترتيب_المبيعات" و "معرف_الوالد" في جدول "عنوان_المبيعات" ( `soa` alias)). الآن ، لدينا حق الوصول إلى بيانات عنوان تسليم طلب العميل ، والتي يمكننا استخدامها لتحديد "معرف_المنطقة". وهو موجود كرقم في جدول "sales_order_address". يتوافق هذا الرقم مع الفهرس في جدول "directory_country_region" (الاسم المستعار "dcrt"). نظرًا لأننا نحتاج إلى هذا الرمز الإقليمي من الجدول كما هو مذكور أعلاه ، فلنقم بتوصيل عمود "الكود". سيحصل هذا العمود الدقيق على الإخراج (يتوافق مع قيمة "العمود" في "sales_order_grid.xml").
بعد ذلك ، امسح ذاكرة التخزين المؤقت:
> 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" إذا لزم الأمر.
كيف تضيف عمود إضافي؟
إذا قررت إضافة عمود آخر ، من فضلك ، اتبع الإرشادات الموضحة في الالتزام Git التالي: https://github.com/mageworx/articles-extended-orders-grid/commit/d31c364a25ce493ab64731c5ca0481e146dbbac3
هناك ، أضفنا عمود telephone
إلى الشبكة من جدول sales_order_address
لعنوان نوع shipping
. كما ترى في رمز التنفيذ ، لم تكن هناك حاجة إلى تعديلات مهمة في التعليمات البرمجية.
بالإضافة إلى ذلك ، يمكن تصدير هذه الأعمدة بنجاح من واجهة "شبكة الطلب" القياسية.
إليك كيف تبدو الشبكة مع عمود "الهاتف":
في لقطة الشاشة أدناه ، يمكنك مشاهدة نفس الطلبات التي تم تصديرها إلى ملف .csv:
[تحديث] كيفية إضافة عمود بمعلومات عناصر الطلب؟
كما تعلم ، تحتوي جميع الطلبات على عناصر الكمية ، بدءًا من واحد إلى خارج الرقم (نعم ، حلم التجار). ولكن كيف يمكننا عرض هذه المعلومات في شبكة الطلبات لبدء البحث أو إجراء تحليل بسهولة أكبر؟
لا يمكننا إضافة عمود فقط كما فعلنا سابقًا لأننا نحصل على اسم منتج واحد أو 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) { ...
للحصول على البيانات المطلوبة في عمود واحد ، يجب علينا إنشاء تحديد فرعي بعمودين: order_id
و name
(اسم المنتج) في التحديد الفردي ، والذي يمكن ضمه إلى المجموعة الرئيسية لاحقًا:
// 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']
هو العمود الوحيد الذي تتم إضافته إلى النتيجة ، لأننا لسنا بحاجة إلى معلومات أخرى.
النتيجة النهائية متاحة في المستودع الرسمي لهذا المثال.
إليك رابط الالتزام المحدد: https://github.com/mageworx/articles-extended-orders-grid/commit/0cdffcd4ba66cacb2fd857ba7626fdbcfc0d6fe3
إليك كيف يبدو هذا العمود على مضيفنا المرحلي:
وها هي نتيجة التصدير (CSV):
إليك كيف يبدو طلب البحث عند محاولة البحث عن الطلبات باستخدام المنتجات "السوداء" (على مضيف التطوير لدينا):
حدد main_table
. * ، soat
. telephone
، dcrt
. code
soi
. name
من 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
مثل "٪ Black٪"
من الواضح أن هذه ليست أسرع طريقة لإخراج البيانات. ومع ذلك ، ربما يكون هذا هو الأسهل. أفضل طريقة هي تجميع البيانات حول أسماء المنتجات في عمود منفصل من جدول منفصل (order_id ، products_name) وإضافة هذا الجدول دون تجميع إضافي وأي تحديد فرعي.
لهذا الغرض ، نضيف المجموعة ('order_id') إلى تحديدنا (في نهاية كود الطريقة).
التحديد يعني عنصرًا.
المجموعة تعني طريقة التحديد.
أعتقد أن هذا كل شيء. إذا كان لديك أي أسئلة أو طلبات ، فيرجى ترك تعليق في حقل التعليق.