Magento 2: phần mở rộng, đọc trình xử lý và lưu trình xử lý


9

Ai đó có thể giải thích cho tôi cách sử dụng ReadHandler, SaveHandler và việc sử dụng EntityManager / ExtensionPool không?

Tôi đang cố quấn đầu quanh nó, nhưng tôi không thể hiểu được cách thực hiện nó. Nếu tôi hiểu chính xác, chúng có thể được sử dụng để thực hiện các hoạt động liên tục bổ sung trên các đối tượng, như tạo quan hệ nhiều-nhiều, giống như chúng được sử dụng trong mô-đun CMS để liên kết thực thể với cửa hàng.

Tôi đang cố gắng làm điều tương tự bằng cách liên kết một thực thể khác với các trang CMS, nhưng tôi dường như không thể làm cho nó hoạt động. Đó là, nếu tôi đang sử dụng mẫu thiết kế này đúng cách.

Bất cứ ai có thể chia sẻ một số ánh sáng về điều này? Tôi xin lỗi tôi không thể chia sẻ một số mã tại thời điểm này, vì tôi không làm việc.

EDIT: Đây là mã tôi hiện đang sử dụng:

Tôi đã thêm vào cms_page_form.xmlcác mô-đun của view/adminhtml/ui_componentmình, vì vậy tôi có thêm một tab hiển thị các nhóm khách hàng:

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="customer_groups">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="collapsible" xsi:type="boolean">true</item>
                <item name="label" xsi:type="string" translate="true">Customer Groups</item>
                <item name="sortOrder" xsi:type="number">100</item>
            </item>
        </argument>
        <field name="customer_groups">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="object">Magento\Customer\Model\Config\Source\Group\Multiselect</item>
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">int</item>
                    <item name="label" xsi:type="string" translate="true">Customer Groups</item>
                    <item name="formElement" xsi:type="string">multiselect</item>
                    <item name="source" xsi:type="string">page</item>
                    <item name="dataScope" xsi:type="string">customer_group</item>
                    <item name="default" xsi:type="string">0</item>
                </item>
            </argument>
        </field>
    </fieldset>
</form>

Những công việc này; tab được hiển thị và các nhóm khách hàng được hiển thị. Không có cái nào được chọn theo mặc định.

Đây là mục nhập của tôi trong toàn cầu di.xmlđể đăng ký trình xử lý lưu và đọc của tôi. Cảm hứng của tôi là nhìn vào cách các cửa hàng được lưu trên các trang CMS:

<type name="Magento\Framework\EntityManager\Operation\ExtensionPool">
    <arguments>
        <argument name="extensionActions" xsi:type="array">
            <item name="Magento\Cms\Api\Data\PageInterface" xsi:type="array">
                <item name="read" xsi:type="array">
                    <item name="customerGroupReader"
                          xsi:type="string">Vendor\Module\Model\ResourceModel\Page\Relation\CustomerGroup\ReadHandler</item>
                </item>
                <item name="create" xsi:type="array">
                    <item name="customerGroupCreator"
                          xsi:type="string">Vendor\Module\Model\ResourceModel\Page\Relation\CustomerGroup\SaveHandler</item>
                </item>
                <item name="update" xsi:type="array">
                    <item name="customerGroupUpdater"
                          xsi:type="string">Vendor\Module\Model\ResourceModel\Page\Relation\CustomerGroup\SaveHandler</item>
                </item>
            </item>
        </argument>
    </arguments>
</type>

Đây là xử lý tiết kiệm của tôi:

<?php

namespace Vendor\Module\Model\ResourceModel\Page\Relation\CustomerGroup;

use Magento\Framework\EntityManager\Operation\ExtensionInterface;
use Magento\Cms\Model\ResourceModel\Page as PageResource;

/**
 * Class SaveHandler
 */
class SaveHandler implements ExtensionInterface
{
    /**
     * @var PageResource
     */
    protected $pageResource;

    /**
     * SaveHandler constructor.
     * @param PageResource $pageResource
     */
    public function __construct(
        PageResource $pageResource
    )
    {
        $this->pageResource = $pageResource;
    }

    /**
     * @param \Magento\Cms\Model\Page $entity
     * @param array $arguments
     */
    public function execute($entity, $arguments = [])
    {
        $connection = $this->pageResource->getConnection();

        // First delete all existing relations:
        $connection->delete('cms_page_customer_group', sprintf('page_id = %d', (int) $entity->getId()));

        // Re-create the relations:
        foreach ($entity->getData('customer_group') as $customerGroupId) {
            $connection->insert('cms_page_customer_group', [
                'page_id' => (int) $entity->getId(),
                'customer_group_id' => (int) $customerGroupId
            ]);
        }

        return $entity;
    }
}

Cho đến thời điểm này mọi thứ hoạt động. Nếu tôi chọn các nhóm khách hàng trong quản trị viên, trình xử lý lưu sẽ được thực thi và các hàng thích hợp được thêm vào cơ sở dữ liệu.

Đây là xử lý đọc của tôi:

<?php

namespace Vendor\Module\Model\ResourceModel\Page\Relation\CustomerGroup;

use Magento\Framework\EntityManager\Operation\ExtensionInterface;
use Magento\Cms\Model\ResourceModel\Page as PageResource;

/**
 * Class ReadHandler
 */
class ReadHandler implements ExtensionInterface
{
    /**
     * @var PageResource
     */
    protected $pageResource;

    /**
     * SaveHandler constructor.
     * @param PageResource $pageResource
     */
    public function __construct(
        PageResource $pageResource
    ) {
        $this->pageResource = $pageResource;
    }

    /**
     * @param \Magento\Cms\Model\Page $entity
     * @param array $arguments
     */
    public function execute($entity, $arguments = [])
    {
        if ($entity->getId()) {
            $connection = $this->pageResource->getConnection();

            $customerGroupIds = $connection
                ->fetchCol(
                    $connection
                        ->select()
                        ->from('cms_page_customer_group', ['customer_group_id'])
                        ->where('page_id = ?', (int)$entity->getId())
                );

            $entity->setData('customer_group', $customerGroupIds);
        }

        return $entity;
    }
}

Đây là nơi tôi bị mắc kẹt. Trình xử lý làm việc và được thực hiện. Nếu tôi thực hiện một var_dump()trên $customerGroupIdshọ sẽ được điền bằng kết quả chính xác từ cơ sở dữ liệu.

Tuy nhiên, trong adminhtml, không có nhóm khách hàng nào trong multiselect được chọn. Tôi nghĩ rằng tôi thực sự gần gũi với việc giải quyết vấn đề này, nhưng tôi không thể hiểu mình đang làm gì sai. Ruột của tôi nói với tôi rằng nó có thể có liên quan đến cách tôi tuyên bố multiselect trong cms_page_form.xml, nhưng tôi không chắc nó là gì.

Nhân tiện, đây là một ví dụ về sơ đồ cơ sở dữ liệu:

|page_id|customer_group_id|
|-------|-----------------|
|29     |1                |
|29     |2                |

Mọi sự trợ giúp sẽ rất được trân trọng.


Tôi đang sử dụng phương pháp lưu, giống như bạn Tôi đã sử dụng tài liệu tham khảo từ mô-đun Trang CMS. Nhưng SaveHandler và ReadHandler đều không hoạt động trong trường hợp của tôi. Bạn có bất cứ ý tưởng về điều đó.
Gaurav Khatri

Tôi save handlerkhông được gọi. Đọc Handler đang được gọi. Theo cách tiếp cận tương tự. Tôi đang thiếu gì?
Adarsh ​​Khatri

Câu trả lời:


3

Tôi tìm thấy một câu trả lời về câu hỏi của riêng tôi (mặc dù tôi không chắc chắn nếu nó các câu trả lời):

Trình xử lý đọc hoạt động như mong đợi và đảm bảo rằng dữ liệu được thêm vào mô hình của tôi nếu tôi tải nó (ví dụ) bằng cách sử dụng kho lưu trữ.

Vì vậy, điều đó chỉ để lại cho tôi với admingrid. Sau khi xem qua bản gốc, cms_page_form.xmltôi nhận thấy rằng dữ liệu của biểu mẫu đã được điền bằng cách sử dụng Magento\Cms\Model\Page\DataProvider. Khi tôi nhìn vào lớp này, tôi nhận thấy một phương thức được gọi là getData()sử dụng bộ sưu tập để tìm nạp các thực thể, không phải kho lưu trữ. Có lẽ bởi vì nhà cung cấp dữ liệu là một khái niệm chung cũng có thể được sử dụng trong lưới và công cụ (vui lòng sửa lại cho tôi nếu tôi sai).

Và bộ sưu tập đã không tính ReadHandlerđến. Tôi đã xem bộ sưu tập và các đối tượng getItems()và công cụ, nhưng tôi không thể tìm thấy một cách thích hợp để thêm thuộc tính tùy chỉnh của mình.

Vì vậy, tôi đã kết thúc với việc viết một plugin cho Magento\Cms\Model\Page\DataProvider::getData.

di.xml:

<!--
    Plugin to add customer_group to dataprovider:
-->
<type name="Magento\Cms\Model\Page\DataProvider">
    <plugin name="private_pages_cms_dataprovider"
            type="Vendor\Module\Plugin\Magento\Cms\Model\Page\DataProvider"/>
</type>

Và mã plugin của tôi:

/**
 * @param \Magento\Cms\Model\Page\DataProvider $subject
 * @param array $result
 * @return array
 */
public function afterGetData(\Magento\Cms\Model\Page\DataProvider $subject, array $result)
{
    foreach ($result as $pageId => &$data) {
        $data['customer_group'] = ...
    }
    return $result;
}

Vì vậy, điều này hoạt động ngay bây giờ, nhưng tôi không chắc liệu đây có phải là cách phù hợp hay không - Magento - cách giải quyết vấn đề này. Bất cứ ai có thể chia sẻ một số suy nghĩ về điều này?


1
Tôi nghĩ rằng bạn đang thiếu HydratorPool :)
Keyur Shah

@KeyurShah Tôi đã nhận được hydratorPoolcũng như attributePool, trình xử lý đọc đang được gọi nhưng không lưu trình xử lý. Bất kỳ ý tưởng?
Adarsh ​​Khatri

0

Trong ResourceModel \ Page của bạn, bạn nên thêm chức năng lưu enitityManager; vấn đề làm việc với mã theo sau:

namespace <your namespace>
use Magento\Framework\Model\AbstractModel;
use Magento\Framework\EntityManager\EntityManager;

     ...

    /**
     * @var EntityManager
     */
    protected $entityManager;


public function __construct(
        ...
        EntityManager $entityManager
    )
    {
        ...
        $this->entityManager = $entityManager;
        ...
    }
...
...

 /**
     * @param AbstractModel $object
     * @return $this
     * @throws \Exception
     */
    public function save(AbstractModel $object)
    {
        $this->entityManager->save($object);
        return $this;
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.