Magento 2 Orders 그리드에 필터가 있는 열을 추가하는 방법은 무엇입니까?

게시 됨: 2020-02-03

종종 Magento 2 매장 관리자는 주문 그리드를 사용하고 맞춤화할 때 추가 옵션이 필요합니다. 특정 기본 매개변수를 기반으로 필터링하는 것은 정말 어려운 일이 될 수 있습니다.

최근에 Magento 개발자가 저에게 질문을 해왔습니다. 그는 Magento 2.3.1에서 오더 그리드를 확장하려고 했습니다. 웹에서 볼 수 있는 오래된 게시물은 도움이 되지 않았습니다. 자연스럽게 지난 2년 동안 Magento에서 많은 것이 변경되었습니다.

그의 질문에 따라 특정 사례에 대한 솔루션을 살펴보도록 제안합니다.

주문 그리드에 구매를 완료한 고객의 일부 지역 코드가 포함된 열을 추가해야 합니다. 또한 상점 관리자는 새로 추가된 이 열을 기준으로 주문을 필터링할 수 있어야 합니다.

쉬워 보이지만 주의해야 할 몇 가지 사항이 있습니다. 예를 들어 가상 주문의 경우 구매한 구매자는 배송 주소가 없을 수 있습니다. 아니면 지역을 어떻게 나열할까요? 개발에 착수할 때 이 모든 것을 고려해야 합니다. 앞서 언급한 질문을 바탕으로 다음을 가정해 보겠습니다.

  • 가상 제품에는 배송 지역('null')이 없습니다. 이렇게 하면 이 매개변수를 기반으로 선택하는 데 도움이 됩니다.
  • 지역이 나열되고 기본 Magento 2에서와 같이 레이블로 변환되지 않은 코드 모양을 갖게 됩니다.

*이 기사의 끝에 GitHub에서 공개 액세스가 가능한 모듈에 대한 링크가 있습니다. 하지만 이 문서를 완료하지 못한 경우 이 단락에 링크를 포함합니다: https://github.com/mageworx/articles-extended-orders-grid.

그러나 시간이 부족하더라도 계속 읽으실 것을 권합니다.?

따라서 주문 그리드에 새 열을 추가하려면 다음을 수행해야 합니다.

목차

  • 1. 새 모듈 만들기
  • 2. 그리드에 열 추가
    • 설명
  • 3. 열에 데이터 추가
  • 추가 열을 추가하는 방법?
  • [업데이트] 주문 항목 정보가 있는 열을 추가하는 방법은 무엇입니까?

1. 새 모듈 만들기

먼저 모듈 및 공급업체 이름을 결정하겠습니다. 음, 벤더 이름을 선택할 필요가 없습니다. MageWorx입니다. 여전히 모듈 이름을 선택해야 합니다. ExtendedOrdersGrid 로 설정합니다. 실제로 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만 알고 있는 사람들을 위해 이 단락의 끝에 몇 가지 설명을 추가하겠습니다.

표준 `columns` 노드를 사용하여 그리드에 열을 추가했습니다. 여기서 'code' 이름 아래에 새 열도 추가됩니다. 다음으로 그리드에 열의 속성을 작성해 보겠습니다.

1) 구성품 . 이 열의 생성 및 처리를 담당하는 JS 클래스입니다. 다음 주소의 Magento_Ui 모듈에 있습니다.

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

사실, 당신이 호기심 많은 개발자라면, 다른 깨달음도 살펴보십시오. 흥미로운 것들이 많이 있습니다.

2) 라벨. 이것은 최종 사용자에게 표시될 열 이름이 있는 행입니다. `translate` 속성이 설정된 경우 i18n 현지화 파일에 추가하는 것을 잊지 마십시오. ?

3) 정렬 순서. 그리드의 열 위치입니다. 스토어 관리자가 관리한 적이 없는 모듈이 Magento 2에 설치된 경우 효과가 있습니다. 그렇지 않으면 사용 중인 Magento 2에서 우리가 무엇을 하든 목록 끝에 열이 추가됩니다.

4) 정렬합니다. 이것은 열 내용을 정렬하는 것을 의미합니다. 나는 그것이 분명하다고 생각합니다.

5) 데이터 유형. 이것은 우리가 조작할 데이터 유형입니다. 우리의 경우 그것은 단순히 한 줄의 텍스트입니다. 그러나 목록 또는 부울 값이 될 수 있으며 예를 들어 제품 수량에 대해 이야기하는 경우 숫자가 될 수 있습니다.

6) 보이는. 이것은 그리드가 이전에 사용되었는지 여부에 따라 많이 달라지지만 열 가시성 외에 다른 것은 아닙니다.

그리드에 대한 모든 데이터는 Magento 데이터베이스의 `ui_bookmark` 테이블에 저장됩니다. 따라서 모듈 설치 당시 수정된 그리드에 대한 컬럼에 대한 기록이 없다면 기적을 기대하지 마십시오.

7) 필터 . 이것은 필터 유형입니다. 여기에서 필터링이 일반 텍스트와 같이 수행되어야 한다고 지정했습니다. 코드를 실행하는 동안 MySQL `LIKE %value%` 조건으로 변환됩니다.


MageWorx Magento 2 확장

설명

긴 이야기를 짧게 하려면 확장된 UI 구성 요소의 이름이 원본의 이름과 일치해야 합니다. 우리의 경우 `vendor/magento/module-sales/view/adminhtml/ui_component/sales_order_grid.xml`이고 `view/adminhtml/ui_component/sales_order_grid.xml` 모듈 루트에서 계산됩니다.

UI 그리드 자체는 다음과 같이 `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>

이것은 블록의 경우와 마찬가지로 *이 UI 구성요소를 'sales_order_grid' 이름으로 페이지 콘텐츠에 추가*한다는 의미입니다. 그러나 블록 대신 속성과 제한이 있는 'uiComponent'가 있습니다.


이제 다음 명령을 사용하여 Magento 2 캐시를 지웁니다.

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

주문 그리드에서 결과를 확인합니다.

Magento 2 Orders 그리드에 필터가 있는 열을 추가하는 방법은 무엇입니까? | MageWorx Magento 블로그

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가 이에 대한 데이터를 얻으려고 시도할 때, 우리는 `order_id`(`sales_order_grid` 테이블의 `entity_id` 및 `sales_order_address` 테이블의 `parent_id`로 `sales_order_address` 주소가 있는 테이블의 조인을 만듭니다. `soa` 별칭)). 이제 'region_id'를 결정하는 데 사용할 수 있는 고객의 주문 배송 주소 데이터에 액세스할 수 있습니다. `sales_order_address` 테이블에 숫자로 있습니다. 이 숫자는 `directory_country_region` 테이블(`dcrt` 별칭)의 인덱스에 해당합니다. 위에서 언급한 표에서 이 지역 코드가 필요하므로 '코드' 열을 연결해 보겠습니다. 이 정확한 열은 출력을 얻습니다(`sales_order_grid.xml`의 `column` 값에 해당).

그런 다음 캐시를 지웁니다.

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

주문 그리드에 관리자 패널에 로그인합니다. 모든 것이 올바르게 완료되면 지역 코드가 표시됩니다.

Magento 2 Orders 그리드에 필터가 있는 열을 추가하는 방법은 무엇입니까? | MageWorx Magento 블로그

모듈에 대한 무료 액세스는 GitHub: https://github.com/mageworx/articles-extended-orders-grid에서 사용할 수 있습니다.

중요한 사이드노트!

이 열에 데이터를 추가하려면 'your_column_name' 열을 가져와야 하며 컬렉션을 만들 때 필요한 모든 데이터를 추가해야 합니다. 즉, 다른 작업을 수행해야 합니다. 테이블 이름을 바꾸고 고유한 조인을 작성해야 합니다. 또한 필요한 경우 `sales_order_grid.xml` 파일에서 열 이름을 편집하는 것을 잊지 마십시오.

추가 열을 추가하는 방법?

열을 하나 더 추가하기로 결정한 경우 다음 Git 커밋에 설명된 지침을 따르십시오.

여기에서 shipping 유형의 주소에 대한 sales_order_address 테이블의 그리드에 telephone 열을 추가했습니다. 커밋 코드에서 볼 수 있듯이 중요한 코드 수정이 필요하지 않았습니다.

또한 이러한 열은 표준 '주문 그리드' 인터페이스에서 성공적으로 내보낼 수 있습니다.

'전화' 열이 있는 그리드는 다음과 같습니다.

Magento 2 Orders 그리드에 필터가 있는 열을 추가하는 방법은 무엇입니까? | MageWorx Magento 블로그

아래 스크린샷에서 .csv 파일로 내보낸 동일한 주문을 볼 수 있습니다.

Magento 2 Orders 그리드에 필터가 있는 열을 추가하는 방법은 무엇입니까? | MageWorx Magento 블로그

[업데이트] 주문 항목 정보가 있는 열을 추가하는 방법은 무엇입니까?

아시다시피, 모든 주문에는 하나에서 시작하여 숫자를 넘어서는 항목 수량이 있습니다(예, 상인의 꿈). 그러나 검색을 시작하거나 더 쉽게 분석을 실행하기 위해 주문 그리드에 해당 정보를 표시하는 방법은 무엇입니까?

이 경우 각 행에 하나의 제품 이름 또는 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_idname (제품 이름)이라는 두 개의 열이 있는 하위 선택을 만들어야 합니다. 이 열은 나중에 기본 컬렉션에 결합될 수 있습니다.

 // 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 \',\')') 표현식을 사용하여 그룹화해야 합니다. 이를 위해 나중에 select에 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

스테이징 호스트에서 해당 열이 어떻게 보이는지 보여줍니다.

?‍? Magento 2 Orders 그리드에 필터가 있는 열을 추가하는 방법은 무엇입니까? | MageWorx Magento 블로그

내보내기(CSV) 결과는 다음과 같습니다.

내보내기(CSV) 결과는 다음과 같습니다.

다음은 "검은색" 제품으로 주문을 검색할 때의 쿼리 모양입니다(개발 호스트에서).
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 = '배송'
LEFT JOIN directory_country_region AS dcrt ON soat.region_id = dcrt.region_id
LEFT JOIN (SELECT GROUP_CONCAT(DISTINCT 이름 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 LIKE '%Black%'

분명히 이것은 데이터를 출력하는 가장 빠른 방법은 아닙니다. 그러나 그것이 아마도 가장 쉬운 방법일 것입니다. 가장 좋은 방법은 별도의 테이블(order_id, products_name)의 별도 열에 제품 이름에 대한 데이터를 축적하고 추가 그룹화 및 하위 선택 없이 이 테이블을 추가하는 것입니다.

이를 위해 그룹('order_id')을 선택 항목에 추가합니다(메서드 코드 끝 부분에 있음).
선택은 요소를 의미합니다.
그룹은 선택 방법을 의미합니다.


그게 다야. 질문이나 요청 사항이 있으면 댓글 필드에 댓글을 남겨주세요.