Magento 2:拡張プール、読み取りハンドラー、保存ハンドラー


9

ReadHandler、SaveHandlerの使用方法、およびEntityManager / ExtensionPoolの使用について誰かに説明してもらえますか?

頭を回そうとしているのですが、実装方法がよくわかりません。私が正しく理解している場合は、これらを使用して、オブジェクトをストアにリンクするためにCMSモジュールで使用されるような、多対多の関係の作成など、オブジェクトに対する追加の永続的な操作を実行できます。

別のエンティティをCMSページに関連付けることによって同じことを実行しようとしていますが、機能させることができません。つまり、このデザインパターンを適切に使用している場合です。

誰かがこれについていくつかの光を共有できますか?私は仕事をしていないので、現時点では一部のコードを共有できません。

編集:これは私が現在使用しているコードです:

cms_page_form.xmlモジュールの- view/adminhtml/ui_componentフォルダーに追加したので、顧客グループを表示する追加のタブがあります。

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

これは機能します。タブがレンダリングされ、顧客グループが表示されます。デフォルトでは何も選択されていません。

これは、di.xml私の保存ハンドラと読み取りハンドラを登録するための私のグローバルのエントリです。私のインスピレーションは、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>

これは私の保存ハンドラです:

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

この時点まで、すべてが機能します。管理で顧客グループを選択すると、保存ハンドラーが実行され、適切な行がデータベースに追加されます。

これは私の読み取りハンドラです:

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

これは私が行き詰まっているところです。ハンドラーが機能し、実行されます。を実行するvar_dump()$customerGroupIds、データベースからの正しい結果が表示されます。

ただし、adminhtmlでは、複数選択の顧客グループはどれも選択されていません。私はこれを解決することに非常に近いと思いますが、私が間違っていることを理解することはできません。私の直感はcms_page_form.xml、それがで複数選択をどのように宣言したかと関係があるかもしれないと私に言っていますが、それが何であるかはわかりません。

ちなみに、これはデータベーススキーマの例です。

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

どんな助けでも大歓迎です。


CMSページモジュールからの参照を使用したのと同じように、保存方法を使用しています。しかし、私の場合、SaveHandlerとReadHandlerはどちらも機能しません。それについて何かご存知ですか?
Gaurav Khatri 2018

save handlerは呼ばれていません。読み取りハンドラが呼び出されています。同じアプローチに従います。何が欠けていますか?
Adarsh Khatri

回答:


3

私は自分の質問に答えを見つけました(それ答えかどうかはわかりません):

読み取りハンドラーは期待どおりに機能し、リポジトリーを使用して(たとえば)データをロードすると、データが確実にモデルに追加されます。

そのため、管理グリッドが残りました。オリジナルcms_page_form.xmlを調べたところ、フォームのデータがを使用して入力されていることに気付きましたMagento\Cms\Model\Page\DataProvider。このクラスを見て、リポジトリではなくコレクションgetData()使用してエンティティをフェッチするという呼び出されたメソッドに気づきました。おそらく、データプロバイダーはグリッドやその他のものでも使用できる一般的な概念であるためです(私が間違っている場合は修正してください)。

そして、コレクションはReadHandler考慮に入れませんでした。コレクションと- getItems()メソッドなどを確認しましたが、カスタム属性を追加する適切な方法が見つかりませんでした。

だから私はのプラグインを書くことになった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>

そして私のプラグインコード:

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

だからこれは今は機能しますが、これが適切な方法であるかどうかはわかりません-Magento-これに対処する方法。誰かがこれについていくつかの考えを共有できますか?


1
HydratorPoolが不足していると思います:)
Keyur Shah

@KeyurShah hydratorPoolだけでなくattributePool、読み取りハンドラが呼び出されていますが、保存ハンドラはありません。何か案が?
Adarsh Khatri

0

ResourceModel \ Pageに、関数save enitityManagerを追加する必要があります。問題は次のコードで機能しました:

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;
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.