私はコアを見渡して、モデル間の多対多の関係のいくつかの例を見てきましたが、これに関する明確な答えを見ることができません。
例として、新しいモデルを作成し、既存の製品テーブルと多対多の関係を持ちたいとします。
新しいモデル-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のコア内のいくつかの同様のコードに基づいていますが、より良い方法があるかどうか疑問に思わずにはいられませんか?