Magento 2: расширение пула, обработчики чтения и сохранения


9

Может кто-нибудь объяснить мне, как использовать ReadHandler, SaveHandler и использование EntityManager / ExtensionPool?

Я пытаюсь обернуть голову вокруг этого, но я не совсем понимаю, как это реализовать. Если я правильно понимаю, их можно использовать для выполнения дополнительных постоянных операций над объектами, таких как создание отношений «многие ко многим», как они используются в модуле CMS для связи объекта с хранилищем.

Я пытаюсь сделать то же самое, связывая другую сущность со страницами CMS, но я не могу заставить ее работать. То есть, если я правильно использую этот шаблон дизайна.

Кто-нибудь может поделиться некоторым светом на это? Извините, я не могу поделиться некоторым кодом в данный момент, так как я не на работе.

РЕДАКТИРОВАТЬ: Это код, который я в настоящее время использую:

Я добавил cms_page_form.xmlв view/adminhtml/ui_componentпапку моих модулей , поэтому у меня есть дополнительная вкладка, которая отображает группы клиентов:

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

Это работает; отображается вкладка и отображаются группы клиентов. Ни один не выбран по умолчанию.

Это моя запись в моей глобальной сети di.xmlдля регистрации моих обработчиков сохранения и чтения. Мое вдохновение было связано с тем, как магазины сохраняются на страницах 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>

Это мой обработчик сохранения:

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

До этого момента все работает. Если я выбираю группы клиентов в администраторе, выполняется обработчик сохранения, и соответствующие строки добавляются в базу данных.

Это мой обработчик чтения:

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

Вот где я застрял. Обработчик работает и исполняется. Если я выполнить var_dump()на $customerGroupIdsних заполняются с правильными результатами из базы данных.

Однако в adminhtml ни одна из групп клиентов в множественном выборе не выбрана. Я думаю, что я действительно близок к решению этого, но я не могу понять, что я делаю неправильно. Мои внутренности говорят мне, что это может иметь какое-то отношение к тому, как я объявил множественный выбор cms_page_form.xml, но я не уверен, что это такое.

Кстати, это пример схемы базы данных:

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

Любая помощь будет принята с благодарностью.


Я использую подход сохранения, как и вы, я использовал ссылку из модуля CMS Page. Но SaveHandler и ReadHandler оба не работают в моем случае. У вас есть идеи по этому поводу?
Гаурав Хатри

Моего save handlerне зовут. Обработчик чтения вызывается. Следуя тому же подходу. Что мне не хватает?
Адарш Хатри

Ответы:


3

Я нашел ответ на свой вопрос (хотя я не уверен , если это в ответ):

Обработчик чтения работает должным образом и обеспечивает добавление данных в мою модель, если я загружаю ее (например) с помощью репозитория.

Так что только что оставил меня с админгридом. Посмотрев оригинал, cms_page_form.xmlя заметил, что данные формы были заполнены с помощью Magento\Cms\Model\Page\DataProvider. Когда я посмотрел на этот класс, то заметил метод, getData()который использует коллекцию для извлечения сущностей, а не хранилище. Возможно, потому что поставщик данных - это общая концепция, которая также может использоваться в сетках и прочем (пожалуйста, исправьте меня, если я ошибаюсь).

И коллекция не приняла ReadHandlerво внимание. Я посмотрел на коллекцию, getItems()метод и прочее, но не смог найти правильный способ добавить свой собственный атрибут.

Так что я закончил с написанием плагина для 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>

И мой код плагина:

/**
 * @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;
}

Так что теперь это работает, но я не уверен, что это правильный путь Magento, как с этим бороться. Кто-нибудь может поделиться некоторыми мыслями по этому поводу?


1
Я думаю, что вам не хватает HydratorPool :)
Keyur Shah

@KeyurShah У меня hydratorPoolтак же , как attributePool, прочитать обработчик вызывался , но не сохранить обработчик. Есть идеи?
Адарш Хатри

0

В вашей ResourceModel \ Page, вы должны добавить функцию save enitityManager; проблема работала со следующим кодом:

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;
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.