Який найкращий спосіб роботи в Magento 2 для створення багатьох до багатьох стосунків?


15

Я оглянув серцевину і побачив декілька прикладів багато-багато стосунків між моделями, але не можу побачити остаточної відповіді на це.

Наприклад, скажімо, що ми створюємо нову модель, і ми хочемо мати багато-багато стосунків із існуючою таблицею продуктів.

Отже, у нас є наша нова модель - Stockist, і ми створюємо дві таблиці як такі, одна для зберігання імені 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');

Тоді ми створюємо стандартну модель / ResourceModel / Collection для Stockist так:

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, що містить співвідношення "багато до багатьох":

/**
 * 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, а $ stockistProduct є екземпляром \ OurModule \ Stockist \ Model \ StockistProduct

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

Потім ми можемо створити кожну модель по черзі, переглянувши список повернених ідентифікаторів так, де $ stockistFactory є екземпляром \ OurModule \ Stockist \ Model \ StockistFactory

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

Це все добре працює і базується на деякому подібному коді в ядрі Magento 2, але я не можу не задатися питанням, чи є кращий спосіб?


Я повинен зробити щось дуже схоже ... і це єдина ідея, яку я маю, якщо немає відповідей :(
slayerbleast

Відповіді:


1

Я реалізував подібне до цього рішення. Для кожної СКУ була інформація про "пристосування": рік, марка, модель автомобіля, до якої можна було б застосувати товар (автомобільний аксесуар). Зважаючи на це, це було б найлегше з рідними атрибутами Magento. Просто використовуйте три текстових поля, одне на рік, одне для виготовлення, одне для моделі. Це дозволяє використовувати всі вбудовані функції Magento, такі як пошук та фільтрація за цими атрибутами, а також просте оновлення в майбутньому.

Проблема, як ви описуєте, полягає в тому, що нам потрібно "багато" цих відносин. Ми могли б зробити 30 текстових атрибутів: year1, make1, model1, year2, make2, model2, ... year10, make10, model10. Це може: а), ймовірно, залишить багато порожніх атрибутів, і b) створить штучне обмеження кількості машин, яке підтримує продукт.

Що може працювати, є щось подібне:

Year: ____
Make: ____
Model: ____

Add new YearMakeModel relationship (+)

А потім, натиснувши плюс (+), ви побачите:

Year: ____
Make: ____
Model: ____

Year: ____
Make: ____
Model: ____

Add new YearMakeModel relationship (+)

Такий інтерфейс може бути реалізований за допомогою javascript всередині резервного шаблону теми. Подавши форму, вам потрібно буде надати ці дані Magento як атрибути продукту. Я не думаю, що в даний час існує тип атрибута, який підтримує динамічну довжину. Ви б реалізували спеціальний тип атрибутів. Знову ж таки, це забезпечує підтримку вбудованої функціональності Magento: пошук за введеними атрибутами, легке оновлення цих атрибутів у майбутньому.

Врешті-решт, наш клієнт прийняв рішення заощадити гроші, не застосовуючи це "просте редагування", і замість цього ми заблокували дані у спеціальній таблиці, як ви описуєте. У мене є спеціальний сценарій імпорту, який приймає введення та виведення CSV до таблиці. Пізніше сторінка продукту (ну, його блок) робить запити до цієї таблиці, витягує інформацію про свій SKU і відображається користувачеві як таблиця. Ця таблиця сторінок продукту була бажаною поведінкою клієнта, тому для нас не було сенсу намагатися робити це "Шляхом Magento" та реалізовувати атрибут змінного члена.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.