Magento 2: extensionpool, leggi gestori e salva gestori


9

Qualcuno può spiegarmi come utilizzare ReadHandler, SaveHandler e l'uso di EntityManager / ExtensionPool?

Sto cercando di avvolgerci la testa, ma non riesco proprio a capire come implementarlo. Se ho capito bene, questi possono essere usati per eseguire ulteriori operazioni persistenti sugli oggetti, come la creazione di relazioni molti-a-molti, come se fossero usate nel modulo CMS per collegare l'entità al negozio.

Sto cercando di fare la stessa cosa mettendo in relazione un'altra entità con le pagine CMS, ma non riesco a farlo funzionare. Cioè, se sto usando questo modello di disegno correttamente.

Qualcuno può condividere un po 'di luce su questo? Mi dispiace di non poter condividere un po 'di codice in questo momento, dato che non sono al lavoro.

EDIT: Questo è il codice che sto attualmente usando:

Ho aggiunto cms_page_form.xmlalla view/adminhtml/ui_componentcartella dei miei moduli , quindi ho una scheda aggiuntiva che mostra i gruppi di clienti:

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

Questo funziona; la scheda viene visualizzata e vengono visualizzati i gruppi di clienti. Nessuno è selezionato per impostazione predefinita.

Questa è la mia voce nel mio globale di.xmlper registrare i miei gestori di salvataggio e lettura. La mia ispirazione è stata quella di vedere come i negozi vengono salvati nelle pagine 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>

Questo è il mio gestore di salvataggio:

<?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;
    }
}

Fino a questo punto tutto funziona. Se seleziono gruppi di clienti nell'amministratore, il gestore di salvataggio viene eseguito e le righe appropriate vengono aggiunte al database.

Questo è il mio gestore di lettura:

<?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;
    }
}

Questo è dove sono bloccato. Il gestore lavora e viene eseguito. Se eseguo un var_dump()on $customerGroupIds, vengono popolati con i risultati corretti dal database.

Tuttavia, nel adminhtml, nessuno dei gruppi di clienti nella selezione multipla è selezionato. Penso di essere molto vicino a risolvere questo, ma non riesco a capire cosa sto facendo di sbagliato. Le mie viscere mi dicono che potrebbe avere qualcosa a che fare con il modo in cui ho dichiarato la selezione multipla cms_page_form.xml, ma non sono sicuro di cosa si tratti.

A proposito, questo è un esempio dello schema del database:

|page_id|customer_group_id|
|-------|-----------------|
|29     |1                |
|29     |2                |

Qualsiasi aiuto sarebbe molto apprezzato.


Sto usando l'approccio di salvataggio, come te ho usato il riferimento dal modulo Pagina CMS. Ma SaveHandler e ReadHandler non funzionano entrambi nel mio caso. Ne hai idea.
Gaurav Khatri,

Il mio save handlernon viene chiamato. Viene letto il gestore di lettura. Seguendo lo stesso approccio. Cosa mi sto perdendo?
Adarsh ​​Khatri,

Risposte:


3

Ho trovato una risposta sulla mia domanda (anche se non sono sicuro che sia la risposta):

Il gestore di lettura funziona come previsto e si assicura che i dati vengano aggiunti al mio modello se li carico (ad esempio) utilizzando un repository.

Quindi questo mi ha lasciato con l'admingrid. Dopo aver esaminato l'originale, cms_page_form.xmlho notato che i dati del modulo sono stati compilati utilizzando Magento\Cms\Model\Page\DataProvider. Quando ho guardato questa classe ho notato un metodo chiamato getData()che utilizza la raccolta per recuperare le entità, non il repository. Probabilmente perché il fornitore di dati è un concetto generale che può essere utilizzato anche in griglie e cose (correggimi se sbaglio).

E la collezione non ha preso ReadHandlerin considerazione. Ho guardato la collezione, il getItems()metodo e roba del genere, ma non sono riuscito a trovare un modo corretto per aggiungere il mio attributo personalizzato.

Così ho finito per scrivere un plugin per 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>

E il mio codice 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;
}

Quindi funziona ora, ma non sono sicuro che questo sia il modo giusto - Magento - di come gestirlo. Qualcuno può condividere alcuni pensieri su questo?


1
Penso che ti manchi HydratorPool :)
Keyur Shah,

@KeyurShah Io ho hydratorPoolcosì come attributePool, gestore di lettura è sempre chiamato, ma non Salva gestore. Qualche idea?
Adarsh ​​Khatri,

0

In ResourceModel \ Page, è necessario aggiungere la funzione save enitityManager; il problema ha funzionato con il seguente codice:

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;
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.