Может кто-нибудь объяснить мне, как использовать 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 |
Любая помощь будет принята с благодарностью.
источник
save handler
не зовут. Обработчик чтения вызывается. Следуя тому же подходу. Что мне не хватает?Ответы:
Я нашел ответ на свой вопрос (хотя я не уверен , если это в ответ):
Обработчик чтения работает должным образом и обеспечивает добавление данных в мою модель, если я загружаю ее (например) с помощью репозитория.
Так что только что оставил меня с админгридом. Посмотрев оригинал,
cms_page_form.xml
я заметил, что данные формы были заполнены с помощьюMagento\Cms\Model\Page\DataProvider
. Когда я посмотрел на этот класс, то заметил метод,getData()
который использует коллекцию для извлечения сущностей, а не хранилище. Возможно, потому что поставщик данных - это общая концепция, которая также может использоваться в сетках и прочем (пожалуйста, исправьте меня, если я ошибаюсь).И коллекция не приняла
ReadHandler
во внимание. Я посмотрел на коллекцию,getItems()
метод и прочее, но не смог найти правильный способ добавить свой собственный атрибут.Так что я закончил с написанием плагина для
Magento\Cms\Model\Page\DataProvider::getData
.di.xml
:И мой код плагина:
Так что теперь это работает, но я не уверен, что это правильный путь Magento, как с этим бороться. Кто-нибудь может поделиться некоторыми мыслями по этому поводу?
источник
hydratorPool
так же , какattributePool
, прочитать обработчик вызывался , но не сохранить обработчик. Есть идеи?В вашей ResourceModel \ Page, вы должны добавить функцию save enitityManager; проблема работала со следующим кодом:
источник