Magento 2: ekstensipool, membaca penangan dan menyimpan penangan

9

Adakah yang bisa menjelaskan kepada saya cara menggunakan ReadHandler, SaveHandler dan penggunaan EntityManager / ExtensionPool?

Saya mencoba membungkus kepala saya di sekitarnya, tetapi saya tidak mengerti bagaimana cara mengimplementasikannya. Jika saya mengerti dengan benar, ini dapat digunakan untuk melakukan operasi persisten tambahan pada objek, seperti membuat banyak-ke-banyak hubungan, seperti mereka digunakan dalam modul CMS untuk menautkan entitas ke toko.

Saya mencoba melakukan hal yang sama dengan menghubungkan entitas lain ke halaman CMS, tetapi sepertinya saya tidak bisa membuatnya berfungsi. Yaitu, jika saya menggunakan pola desain ini dengan benar.

Adakah yang bisa berbagi terang tentang ini? Maaf, saya tidak dapat membagikan beberapa kode saat ini, karena saya tidak bekerja.

EDIT: Ini adalah kode yang saya gunakan saat ini:

Saya telah menambahkan folder cms_page_form.xml-modul saya view/adminhtml/ui_component, jadi saya memiliki tab tambahan yang menampilkan grup pelanggan:

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

Ini bekerja; tab diberikan dan grup pelanggan ditampilkan. Tidak ada yang dipilih secara default.

Ini adalah entri saya di global saya di.xmluntuk mendaftarkan penabung dan penangan saya. Inspirasi saya melihat bagaimana toko disimpan di halaman 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>

Ini penangan simpanan saya:

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

Hingga saat ini semuanya berfungsi. Jika saya memilih grup pelanggan di admin, save handler dijalankan dan baris yang tepat ditambahkan ke database.

Ini adalah handler baca saya:

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

Di sinilah aku terjebak. Pawang bekerja dan dieksekusi. Jika saya melakukan var_dump()pada $customerGroupIdsmereka diisi dengan hasil yang benar dari database.

Namun, di adminhtml, tidak ada grup pelanggan di multiselect yang dipilih. Saya pikir saya benar-benar hampir menyelesaikan yang ini, tapi saya tidak tahu apa yang saya lakukan salah. Nyali saya memberi tahu saya bahwa ini mungkin ada hubungannya dengan bagaimana saya menyatakan pilihan ganda cms_page_form.xml, tetapi saya tidak yakin apa itu.

Omong-omong, ini adalah contoh skema basis data:

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

Bantuan apa pun akan sangat dihargai.

Giel Berkers
sumber
Saya menggunakan pendekatan simpan, seperti Anda, saya menggunakan referensi dari modul Halaman CMS. Tapi SaveHandler dan ReadHandler keduanya tidak berfungsi dalam kasus saya. Apakah Anda tahu tentang itu?
Gaurav Khatri
Saya save handlertidak dipanggil. Baca Handler dipanggil. Mengikuti pendekatan yang sama. Apa yang saya lewatkan?
Adarsh ​​Khatri

Jawaban:

3

Saya menemukan jawaban atas pertanyaan saya sendiri (walaupun aku tidak yakin apakah itu yang jawaban):

Read Handler berfungsi seperti yang diharapkan dan memastikan bahwa data ditambahkan ke model saya jika saya memuatnya (misalnya) menggunakan repositori.

Jadi itu baru saja meninggalkan saya dengan admingrid. Setelah melihat-lihat yang asli cms_page_form.xmlsaya perhatikan bahwa data formulir diisi dengan menggunakan Magento\Cms\Model\Page\DataProvider. Ketika saya melihat kelas ini saya perhatikan metode yang disebut getData()yang menggunakan koleksi untuk mengambil entitas, bukan repositori. Mungkin karena penyedia data adalah konsep umum yang juga dapat digunakan dalam kisi-kisi dan barang-barang (tolong perbaiki saya jika saya salah).

Dan koleksi tidak ReadHandlermemperhitungkannya. Saya melihat koleksi dan getItems()-metode dan semacamnya, tetapi saya tidak dapat menemukan cara yang tepat untuk menambahkan atribut khusus saya.

Jadi saya berakhir dengan menulis sebuah plugin untuk 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>

Dan kode plugin saya:

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

Jadi ini berfungsi sekarang, tapi saya tidak yakin apakah ini cara yang tepat - Magento - cara menangani ini. Adakah yang bisa berbagi pemikiran tentang ini?

Giel Berkers
sumber
1
Saya pikir Anda kehilangan HydratorPool :)
Keyur Shah
@KeyurShah saya sudah mendapat hydratorPooljuga attributePool, baca handler dipanggil tetapi tidak menyimpan handler. Ada ide?
Adarsh ​​Khatri
0

Di ResourceModel \ Page Anda, Anda harus menambahkan fungsi save enitityManager; masalah bekerja dengan mengikuti kode:

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
sumber