Magento 2: extensionpool, lire les gestionnaires et enregistrer les gestionnaires

9

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.xmlau view/adminhtml/ui_componentdossier 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.xmlpour 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(), $customerGroupIdsils 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.

Giel Berkers
la source
J'utilise l'approche de sauvegarde, comme vous j'ai utilisé la référence du module CMS Page. Mais SaveHandler et ReadHandler ne fonctionnent pas dans mon cas. Avez-vous une idée à ce sujet?
Gaurav Khatri
Mon save handlerne se fait pas appeler. Le gestionnaire de lecture est appelé. En suivant la même approche. Qu'est-ce que je rate?
Adarsh ​​Khatri

Réponses:

3

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.xmlj'ai remarqué que les données du formulaire étaient remplies à l'aide de Magento\Cms\Model\Page\DataProvider. Quand j'ai regardé cette classe, j'ai remarqué une méthode appelée getData()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 ReadHandleren compte. J'ai regardé la collection et la getItems()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:

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

Et mon code de plugin:

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

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?

Giel Berkers
la source
1
Je pense que vous manquez HydratorPool :)
Keyur Shah
@KeyurShah J'ai hydratorPoolaussi attributePool, le gestionnaire de lecture est appelé mais pas le gestionnaire de sauvegarde. Une idée?
Adarsh ​​Khatri
0

Dans votre ResourceModel \ Page, vous devez ajouter la fonction save enitityManager; le problème a fonctionné avec le code suivant:

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;
    }
huuthai tran
la source