Quelqu'un peut-il m'expliquer comment utiliser ReadHandler, SaveHandler et l'utilisation de EntityManager / ExtensionPool?
J'essaie d'envelopper ma tête, mais je ne comprends pas très bien comment le mettre en œuvre. Si je comprends bien, ceux-ci peuvent être utilisés pour effectuer des opérations persistantes supplémentaires sur des objets, comme la création de relations plusieurs-à-plusieurs, comme ils sont utilisés dans le module CMS pour lier l'entité au magasin.
J'essaie de faire la même chose en reliant une autre entité aux pages CMS, mais je n'arrive pas à le faire fonctionner. Autrement dit, si j'utilise correctement ce modèle de conception.
Quelqu'un peut-il partager quelque chose à ce sujet? Je suis désolé, je ne peux pas partager de code pour le moment, car je ne suis pas à mon travail.
EDIT: Voici le code que j'utilise actuellement:
J'ai ajouté cms_page_form.xml
au view/adminhtml/ui_component
dossier de mes modules , j'ai donc un onglet supplémentaire qui affiche les groupes de clients:
<?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>
Cela marche; l'onglet est rendu et les groupes de clients sont affichés. Aucun n'est sélectionné par défaut.
Ceci est mon entrée dans mon global di.xml
pour enregistrer mes gestionnaires de sauvegarde et de lecture. Mon inspiration était de voir comment les magasins sont enregistrés sur les pages 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>
Voici mon gestionnaire de sauvegarde:
<?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;
}
}
Jusqu'à ce point, tout fonctionne. Si je sélectionne des groupes de clients dans l'administrateur, le gestionnaire de sauvegarde est exécuté et les lignes appropriées sont ajoutées à la base de données.
Voici mon gestionnaire de lecture:
<?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;
}
}
C'est là que je suis coincé. Le gestionnaire fonctionne et est exécuté. Si j'effectue un var_dump()
, $customerGroupIds
ils sont remplis avec les résultats corrects de la base de données.
Cependant, dans l'adminhtml, aucun des groupes de clients de la multisélection n'est sélectionné. Je pense que je suis vraiment proche de résoudre celui-ci, mais je ne peux pas comprendre ce que je fais mal. Mes tripes me disent que cela pourrait avoir quelque chose à voir avec la façon dont j'ai déclaré la multisélection cms_page_form.xml
, mais je ne suis pas sûr de ce que c'est.
Au fait, ceci est un exemple du schéma de base de données:
|page_id|customer_group_id|
|-------|-----------------|
|29 |1 |
|29 |2 |
Toute aide serait grandement appréciée.
la source
save handler
ne se fait pas appeler. Le gestionnaire de lecture est appelé. En suivant la même approche. Qu'est-ce que je rate?Réponses:
J'ai trouvé une réponse à ma propre question (bien que je ne sois pas sûr que ce soit la réponse):
Le gestionnaire de lecture fonctionne comme prévu et s'assure que les données sont ajoutées à mon modèle si je les charge (par exemple) à l'aide d'un référentiel.
Cela m'a donc laissé avec l'admingrid. Après avoir parcouru l'original,
cms_page_form.xml
j'ai remarqué que les données du formulaire étaient remplies à l'aide deMagento\Cms\Model\Page\DataProvider
. Quand j'ai regardé cette classe, j'ai remarqué une méthode appeléegetData()
qui utilise la collection pour récupérer les entités, pas le référentiel. Probablement parce que le fournisseur de données est un concept général qui peut également être utilisé dans les grilles et autres (veuillez me corriger si je me trompe).Et la collection n'a pas pris
ReadHandler
en compte. J'ai regardé la collection et lagetItems()
méthode et d'autres choses, mais je n'ai pas trouvé de moyen approprié d'ajouter mon attribut personnalisé.J'ai donc fini par écrire un plugin pour
Magento\Cms\Model\Page\DataProvider::getData
.di.xml
:Et mon code de plugin:
Donc, cela fonctionne maintenant, mais je ne sais pas si c'est la bonne façon - Magento - de savoir comment gérer cela. Quelqu'un peut-il partager quelques réflexions à ce sujet?
la source
hydratorPool
aussiattributePool
, le gestionnaire de lecture est appelé mais pas le gestionnaire de sauvegarde. Une idée?Dans votre ResourceModel \ Page, vous devez ajouter la fonction save enitityManager; le problème a fonctionné avec le code suivant:
la source