首页>Magento>source

我环顾了核心并看到了模型之间多对多关系的一些例子,但我看不出这方面的明确答案。

作为一个例子,假设我们创建了一个新模型,我们希望与现有产品表有多对多的关系。

所以我们有了新的模型 - Stockist,我们创建了2个表,一个用于存储Stockist名称,另一个用于存储与产品的多对多关系。

设置类的截断版本:

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

这里定义了两个方法,它们将接收一个stockist数组,返回一个匹配的Product Ids数组,反之亦然。

这使用包含多对多关系的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()]);

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

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

这一切都运行良好,并且基于Magento 2核心中的一些类似代码,但我不禁想知道是否有更好的方法?

最新回答
  • 2019-12-5
    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 way"并实现变量成员属性是没有意义的。

  • magento2:Magento 2:购物车流程有什么问题?
  • Magento2在购物车页面上的总计之前添加自定义html