多対多の関係を作成するためのMagento 2のベストプラクティスの方法は何ですか?


15

私はコアを見渡して、モデル間の多対多の関係のいくつかの例を見てきましたが、これに関する明確な答えを見ることができません。

例として、新しいモデルを作成し、既存の製品テーブルと多対多の関係を持ちたいとします。

新しいモデル-Stockistがあり、2つのテーブルを作成します。1つはStockist名を格納し、もう1つは製品との多対多の関係を格納します。

セットアップクラスの短縮バージョン:

$table = $setup->getConnection()
        ->newTable($installer->getTable('stockist'))
        ->addColumn('stockist_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
            null,
            ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
            'Stockist Id')
        ->addColumn('name',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            null,
            ['nullable' => false],
            'Stockist Name');

 $table = $installer->getConnection()
            ->newTable($installer->getTable('stockist_product'))
            ->addColumn(
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['identity' => true, 'nullable' => false, 'primary' => true],
                'Entity ID'
            )
            ->addColumn(
                'stockist_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['unsigned' => true, 'nullable' => false, 'primary' => true, 'default' => '0'],
                'Stockist ID'
            )
            ->addColumn(
                'product_id',
                \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                null,
                ['unsigned' => true, 'nullable' => false, 'primary' => true, 'default' => '0'],
                'Product ID'
            )
            ->addIndex(
                $installer->getIdxName('stockist_product', ['product_id']),
                ['product_id']
            )
            ->addIndex(
                $installer->getIdxName(
                    'stockist_product,
                    ['stockist_id', 'product_id'],
                    \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE
                ),
                ['stockist_id', 'product_id'],
                ['type' => \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE]
            )
            ->addForeignKey(
                $installer->getFkName('stockist_product', 'product_id', 'catalog_product_entity', 'entity_id'),
                'product_id',
                $installer->getTable('catalog_product_entity'),
                'entity_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->addForeignKey(
                $installer->getFkName('stockist_product', 'stockist_id', 'stockist', 'stockist_id'),
                'stockist_id',
                $installer->getTable('stockist'),
                'stockist_id',
                \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
            )
            ->setComment('Stockist to Product Many to Many');

次に、Stockistの標準のModel / ResourceModel / Collectionを作成します。

namespace OurModule\Stockist\Model;

use Magento\Framework\Model\AbstractModel;

class Stockist extends AbstractModel
{

    protected function _construct()
    {
        $this->_init('OurModule\Stockist\Model\ResourceModel\Stockist');
    }

}

namespace OurModule\Stockist\Model\ResourceModel;

use Magento\Framework\Model\ResourceModel\Db\AbstractDb;

class Stockist extends AbstractDb
{

    protected function _construct()
    {
        $this->_init('stockist', 'stockist_id');
    }

}

namespace OurModule\Stockist\Model\ResourceModel\Stockist;

use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;

class Collection extends AbstractCollection
{

    public function _construct()
    {
        $this->_init('OurModule\Stockist\Model\Stockist', 'OurModule\Stockist\Model\ResourceModel\Stockist');
    }

}

ここで、多対多の関係を持つテーブルの処理方法を説明します。これまでのところ、これに沿って何かを思いついた。

StockistProductを表すモデルを作成する

namespace OurModule\Stockist\Model;

use Magento\Framework\Model\AbstractModel;

class StockistProduct extends AbstractModel
{

protected function _construct()
{
    $this->_init('OurModule\Stockist\Model\ResourceModel\StockistProduct');
}

/**
 * @param array $productIds
 */
public function getStockists($productIds)
{
    return $this->_getResource()->getStockists($productIds);
}

/**
 * @param array $stockistIds
 */
public function getProducts($stockistIds)
{
    return $this->_getResource()->getProducts($stockistIds);
}
}

ここでは、仕入先IDの配列のいずれかを受け取る2つのメソッドを定義し、一致する製品IDの配列を返します。その逆も同様です。

これは、多対多の関係を含むstockist_productテーブルにリソースモデルを使用します。

/**
 * Class StockistProduct
 */
class StockistProduct extends AbstractDb
{
    /**
     * Model initialization
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('stockist_product', 'entity_id');
    }

    /**
     * Retrieve product stockist Ids
     *
     * @param array $productIds
     * @return array
     */
    public function getStockists(array $productIds)
    {
        $select = $this->getConnection()->select()->from(
            $this->getMainTable(),
            ['product_id', 'stockist_id']
        )->where(
            'product_id IN (?)',
            $productIds
        );
        $rowset = $this->getConnection()->fetchAll($select);

        $result = [];
        foreach ($rowset as $row) {
            $result[$row['product_id']][] = $row['stockist_id'];
        }

        return $result;
    }


    /**
     * Retrieve stockist product Ids
     *
     * @param array $stockistIds
     * @return array
     */
    public function getProducts(array $stockistIds)
    {
        $select = $this->getConnection()->select()->from(
            $this->getMainTable(),
            ['product_id', 'stockist_id']
        )->where(
            'stockist_id IN (?)',
            $stockistIds
        );
        $rowset = $this->getConnection()->fetchAll($select);

        $result = [];
        foreach ($rowset as $row) {
            $result[$row['product_id']][] = $row['stockist_id'];
        }

        return $result;
    }
}

次に、$ productに製品モデルがあり、$ stockistProductが\ OurModule \ Stockist \ Model \ StockistProductのインスタンスであると仮定して、どちらかのモデルのセットを取得する必要があるときにこのStockistProductモデルを使用します

$stockists = $stockistProduct->getStockists([$product->getId()]);

その後、返されたIDのリストをループすることにより、各モデルを順番に作成できます。$ stockistFactoryは\ OurModule \ Stockist \ Model \ StockistFactoryのインスタンスです

$stockist = $this->stockistFactory->create();
$stockist->load($stockistId);

これはすべて正常に機能し、Magento 2のコア内のいくつかの同様のコードに基づいていますが、より良い方法があるかどうか疑問に思わずにはいられませんか?


私は非常に似たようなことをしなければなりません...そして答えがない場合、これは私が持っている唯一のアイデアです:(
slayerbleast

回答:


1

これに似たソリューションを実装しました。各SKUには、製品(カーアクセサリー)を適用できる車の年、メーカー、モデルなどの「装備」情報がありました。一見すると、これはネイティブのMagento属性を使用すると最も簡単になります。3つのテキストフィールドを使用します。1つは年、1つはメーカー、1つはモデル用です。これにより、これらの属性を使用した検索やフィルタリングなどのすべての組み込みMagento機能が、将来の簡単な更新とともに可能になります。

問題は、あなたが説明するように、これらの関係の「多く」が必要なことです。30個のテキスト属性を作成できます:year1、make1、model1、year2、make2、model2、... year10、make10、model10。これは、a)多くの空の属性を残し、b)製品がサポートする車の数に人為的な制限を作成する可能性があります。

機能するのは次のようなものです。

Year: ____
Make: ____
Model: ____

Add new YearMakeModel relationship (+)

そして、プラス(+)をクリックすると、次のように表示されます。

Year: ____
Make: ____
Model: ____

Year: ____
Make: ____
Model: ____

Add new YearMakeModel relationship (+)

このようなUIは、バッキングされたテーマテンプレート内のjavascriptで実装できます。フォームを送信したら、このデータを製品属性としてMagentoに提供する必要があります。現在、動的な長さをサポートする属性タイプはないと思います。カスタム属性タイプを実装します。繰り返しますが、これは組み込みのMagento機能からのサポートを提供します。入力された属性の検索、将来これらの属性の簡単な更新。

最終的に、クライアントはこの「簡単な編集」を実装しないことでお金を節約することを決定し、代わりに、説明したとおりにカスタムテーブルのデータをロックしました。CSVの入力とテーブルへの出力を行うカスタムインポートスクリプトがあります。その後、製品ページ(そのブロック)がこのテーブルに対してクエリを実行し、そのSKUに関する情報を引き出して、テーブルとしてユーザーに表示します。この製品ページのテーブルはクライアントからの望ましい振る舞いだったので、私たちにとって「The Magento Way」を実行して可変メンバー属性を実装することは意味がありませんでした。

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