Magento 2中创建多对多关系的最佳实践方法是什么?


15

我环顾了核心,并看到了几个模型之间多对多关系的一些示例,但是我看不到对此的明确答案。

例如,假设我们创建了一个新模型,并且希望与现有产品表建立多对多关系。

因此,我们有了新的模型-库存商,我们这样创建了2个表,一个表用于存储库存商名称,另一个用于存储与产品的多对多关系。

安装程序类的截断版本:

$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');

然后,我们为库存商创建一个标准的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);
}
}

在此定义2种方法,这些方法将采用一组库存商ID,然后返回一组匹配的产品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;
    }
}

然后,当您需要检索其中一个模型时,使用此StockistProduct模型,假设我们在$ product中有一个Product Model,并且$ stockistProduct是\ OurModule \ Stockist \ Model \ StockistProduct的实例

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

然后,我们可以循环循环返回的Ids列表,依次创建每个模型,其中$ stockistFactory是\ OurModule \ Stockist \ Model \ StockistFactory的实例

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

一切都很好,并且基于Magento 2核心中的一些类似代码,但是我不禁怀疑是否有更好的方法?


我必须做一些非常相似的事情...这是我唯一的想法,如果没有答案:(
slayerbleast

Answers:


1

我实现了与此类似的解决方案。对于每个SKU,都有“配件”信息:可以应用该产品(汽车配件)的汽车的年份,品牌,型号。从表面上看,使用本地Magento属性最简单。只需使用三个文本字段,一个用于年份,一个用于制造,一个用于模型。这允许使用所有内置的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的信息,并以表的形式显示给用户。该产品页表是客户期望的行为,因此对我们而言,深入研究“ Magento方式”并实现可变成员属性是没有意义的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.