Kann mir jemand erklären, wie man ReadHandler, SaveHandler und den EntityManager / ExtensionPool benutzt?
Ich versuche, meinen Kopf darum zu wickeln, aber ich kann nicht ganz verstehen, wie ich es implementieren soll. Wenn ich das richtig verstehe, können diese verwendet werden, um zusätzliche persistente Vorgänge für Objekte auszuführen, z. B. das Erstellen von Viele-zu-Viele-Beziehungen, wie sie im CMS-Modul zum Verknüpfen der Entität mit dem Geschäft verwendet werden.
Ich versuche das Gleiche zu tun, indem ich eine andere Entität mit CMS-Seiten verknüpfe, aber ich kann es anscheinend nicht zum Laufen bringen. Das heißt, wenn ich dieses Entwurfsmuster richtig verwende.
Kann jemand etwas Licht darauf geben? Es tut mir leid, dass ich derzeit keinen Code freigeben kann, da ich nicht bei meiner Arbeit bin.
EDIT: Dies ist der Code, den ich derzeit verwende:
Ich habe cms_page_form.xml
den view/adminhtml/ui_component
Ordner meiner Module hinzugefügt, sodass ich eine zusätzliche Registerkarte habe, auf der die Kundengruppen angezeigt werden:
<?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>
Das funktioniert; Die Registerkarte wird gerendert und die Kundengruppen werden angezeigt. Standardmäßig sind keine ausgewählt.
Dies ist mein Eintrag in meinem Global di.xml
, um meine Save- und Read-Handler zu registrieren. Meine Inspiration war, wie Geschäfte auf CMS-Seiten gespeichert werden:
<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>
Dies ist mein sicherer Handler:
<?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;
}
}
Bis zu diesem Punkt funktioniert alles. Wenn ich im Administrator Kundengruppen auswähle, wird der Save Handler ausgeführt und die richtigen Zeilen zur Datenbank hinzugefügt.
Dies ist mein Lesehandler:
<?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;
}
}
Hier stecke ich fest. Der Handler arbeitet und wird ausgeführt. Wenn ich ein var_dump()
On durchführe, werden $customerGroupIds
sie mit den richtigen Ergebnissen aus der Datenbank gefüllt.
In der Adminhtml ist jedoch keine der Kundengruppen in der Mehrfachauswahl ausgewählt. Ich denke, ich bin sehr nahe daran, dieses Problem zu lösen, aber ich kann nicht herausfinden, was ich falsch mache. Mein Mut sagt mir, dass es etwas damit zu tun haben könnte, wie ich die Mehrfachauswahl deklariert habe cms_page_form.xml
, aber ich bin mir nicht sicher, was es ist.
Dies ist übrigens ein Beispiel für das Datenbankschema:
|page_id|customer_group_id|
|-------|-----------------|
|29 |1 |
|29 |2 |
Jede Hilfe wäre sehr dankbar.
quelle
save handler
wird nicht angerufen. Read Handler wird aufgerufen. Nach dem gleichen Ansatz. Was vermisse ich?Antworten:
Ich habe eine Antwort auf meine eigene Frage gefunden (obwohl ich nicht sicher bin, ob es die Antwort ist):
Der Read Handler funktioniert wie erwartet und stellt sicher, dass die Daten meinem Modell hinzugefügt werden, wenn ich sie (zum Beispiel) über ein Repository lade.
Das hat mich nur mit dem Admingrid zurückgelassen. Nachdem
cms_page_form.xml
ich das Original durchgesehen hatte, bemerkte ich, dass die Daten des Formulars mit verwendet wurdenMagento\Cms\Model\Page\DataProvider
. Als ich mir diese Klasse ansah, bemerkte ich eine Methode namensgetData()
, die die Sammlung verwendet , um die Entitäten abzurufen, nicht das Repository. Wahrscheinlich, weil der Datenprovider ein allgemeines Konzept ist, das auch in Grids und anderen Dingen verwendet werden kann (bitte korrigieren Sie mich, wenn ich falsch liege).Und die Sammlung
ReadHandler
berücksichtigte dies nicht . Ich habe mir die Sammlung und diegetItems()
Methode und das Zeug angesehen, aber ich konnte keinen geeigneten Weg finden, um mein benutzerdefiniertes Attribut hinzuzufügen.Also habe ich ein Plugin für geschrieben
Magento\Cms\Model\Page\DataProvider::getData
.di.xml
::Und mein Plugin-Code:
Das funktioniert jetzt, aber ich bin mir nicht sicher, ob dies der richtige - Magento - Weg ist, wie man damit umgeht. Kann jemand einige Gedanken dazu teilen?
quelle
hydratorPool
so gut wieattributePool
, lesen Handler wird aufgerufen, aber nicht speichern Handler. Irgendeine Idee?In Ihrem ResourceModel \ Page sollten Sie die Funktion save enitityManager hinzufügen. Das Problem funktionierte mit folgendem Code:
quelle