¿Alguien puede explicarme cómo usar ReadHandler, SaveHandler y el uso de EntityManager / ExtensionPool?
Estoy tratando de entenderlo, pero no puedo entender cómo implementarlo. Si entiendo correctamente, estos se pueden usar para realizar operaciones persistentes adicionales en los objetos, como crear relaciones de muchos a muchos, como se usan en el módulo CMS para vincular la entidad a la tienda.
Estoy tratando de hacer lo mismo relacionando otra entidad con las páginas de CMS, pero parece que no puedo hacer que funcione. Es decir, si estoy usando este patrón de diseño correctamente.
¿Alguien puede compartir algo de luz sobre esto? Lo siento, no puedo compartir un código en este momento, ya que no estoy en mi trabajo.
EDITAR: Este es el código que estoy usando actualmente:
He agregado cms_page_form.xml
a la view/adminhtml/ui_component
carpeta de mis módulos , por lo que tengo una pestaña adicional que muestra los grupos de clientes:
<?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>
Esto funciona; la pestaña se representa y se muestran los grupos de clientes. Ninguno está seleccionado por defecto.
Esta es mi entrada en mi global di.xml
para registrar mis controladores de guardar y leer. Mi inspiración fue ver cómo se guardan las tiendas en las páginas de 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>
Este es mi controlador de guardado:
<?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;
}
}
Hasta este punto todo funciona. Si selecciono grupos de clientes en el administrador, el controlador de guardado se ejecuta y las filas adecuadas se agregan a la base de datos.
Este es mi controlador de lectura:
<?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;
}
}
Aquí es donde estoy atrapado. El controlador funciona y se ejecuta. Si realizo un var_dump()
encendido $customerGroupIds
, se rellenan con los resultados correctos de la base de datos.
Sin embargo, en adminhtml, ninguno de los grupos de clientes en la selección múltiple está seleccionado. Creo que estoy realmente cerca de resolver esto, pero no puedo entender qué estoy haciendo mal. Mis agallas me dicen que podría tener algo que ver con la forma en que declaró la selección múltiple cms_page_form.xml
, pero no estoy seguro de qué es.
Por cierto, este es un ejemplo del esquema de base de datos:
|page_id|customer_group_id|
|-------|-----------------|
|29 |1 |
|29 |2 |
Cualquier ayuda sería muy apreciada.
fuente
save handler
no es llamado. Se llama a Read Handler. Siguiendo el mismo enfoque. ¿Qué me estoy perdiendo?Respuestas:
Encontré una respuesta en mi propia pregunta (aunque no estoy seguro de si es la respuesta):
El controlador de lectura funciona como se espera y se asegura de que los datos se agreguen a mi modelo si lo cargo (por ejemplo) usando un repositorio.
Entonces eso me dejó con el admingrid. Después de mirar el original
cms_page_form.xml
, noté que los datos del formulario se rellenaban mediante el usoMagento\Cms\Model\Page\DataProvider
. Cuando miré esta clase, noté un método llamadogetData()
que usa la colección para buscar las entidades, no el repositorio. Probablemente porque el proveedor de datos es un concepto general que también se puede usar en cuadrículas y otras cosas (corríjame si me equivoco).Y la colección no tuvo
ReadHandler
en cuenta. Miré la colección y elgetItems()
método y esas cosas, pero no pude encontrar una manera adecuada de agregar mi atributo personalizado.Así que terminé escribiendo un complemento para
Magento\Cms\Model\Page\DataProvider::getData
.di.xml
:Y mi código de complemento:
Así que esto funciona ahora, pero no estoy seguro de si esta es la forma correcta, Magento, de cómo lidiar con esto. ¿Alguien puede compartir algunos pensamientos sobre esto?
fuente
hydratorPool
, así comoattributePool
, manejador de lectura está recibiendo llamadas, pero no guardar manejador. ¿Alguna idea?En su ResourceModel \ Page, debe agregar la función save enitityManager; el problema funcionó con el siguiente código:
fuente