0

I have created 2 table :

table_1 :

  • id (Primary key)
  • name
  • status

table_2 :

  • sub_id (Primary key)

  • id (Foreign key table_1 id)

  • description

How to save records in both table using single model file?

0

In my example, I will be adding a new table in MySQL: my_custom_table with two fields: Id: Main key, Item ID

qty: int (11), number of item

You can usually update multiple records in the database using a save () method of model.

app/code/[NameSpace]/[ModuleName]/Model/ResourceModel/Custom.php

$updateData = [1 => 5, 2 =>12, 3 => 16, 4=>5];

$connection = $this->getConnection();

$conditions = [];

foreach ($updateData as $id => $qty) {

$case = $connection->quoteInto('?', $id);

$result = $connection->quoteInto('?', $qty);

$conditions[$case] = $result;

}

$value = $connection->getCaseSql('id', $conditions, 'qty');

$where = ['id IN (?)' => array_keys($updateData)];

try {   

    $connection->beginTransaction();

    $connection->update($this->getTable('my_custom_table'), ['qty' => $value], $where);

    $connection->commit();

} catch(\Exception $e) {

    $connection->rollBack();

}

hope this helps!

0

I got this answer from this blog

https://lorenzosfarra.com/2017/05/19/magento2-database-transactions-how-to-save-multiple-model-instances/

But it makes sense. Something like this:

public function __construct(
    [..]
    \Some\Thing\Model\TableFactory $tableFactory,
    \Some\OtherThing\Model\TableFactory $table2Factory,
    \Magento\Framework\DB\TransactionFactory $transactionFactory
) {
    [..]
    $this->tableFactory = $tableFactory;
    $this->table2Factory = $table2Factory;
    $this->transactionFactory = $transactionFactory;
}
$transaction = $this->transactionFactory->create();

$tableInstance = $this->tableFactory->create();
$tableInstance->setField1($field1);
$transaction->addObject($tableInstance);
$tableInstance2 = $this->table2Factory->create();
$tableInstance2->setField2($field2);
$transaction->addObject($tableInstance2);

$transaction->save(); // single transaction

Another reference

Magento 2 - Database transaction for multiple model / resource model objects?

I can't think of a cleaner way to do it.

Update

CMS module uses extension pool concept. This is really difficult to follow and explain.

https://github.com/magento/magento2/blob/2.3-develop/app/code/Magento/Cms/etc/di.xml#L149-L176

    <type name="Magento\Framework\EntityManager\Operation\ExtensionPool">
        <arguments>
            <argument name="extensionActions" xsi:type="array">
                <item name="Magento\Cms\Api\Data\PageInterface" xsi:type="array">
                    <item name="read" xsi:type="array">
                        <item name="storeReader" xsi:type="string">Magento\Cms\Model\ResourceModel\Page\Relation\Store\ReadHandler</item>
                    </item>
                    <item name="create" xsi:type="array">
                        <item name="storeCreator" xsi:type="string">Magento\Cms\Model\ResourceModel\Page\Relation\Store\SaveHandler</item>
                    </item>
                    <item name="update" xsi:type="array">
                        <item name="storeUpdater" xsi:type="string">Magento\Cms\Model\ResourceModel\Page\Relation\Store\SaveHandler</item>
                    </item>
                </item>
                <item name="Magento\Cms\Api\Data\BlockInterface" xsi:type="array">
                    <item name="read" xsi:type="array">
                        <item name="storeReader" xsi:type="string">Magento\Cms\Model\ResourceModel\Block\Relation\Store\ReadHandler</item>
                    </item>
                    <item name="create" xsi:type="array">
                        <item name="storeCreator" xsi:type="string">Magento\Cms\Model\ResourceModel\Block\Relation\Store\SaveHandler</item>
                    </item>
                    <item name="update" xsi:type="array">
                        <item name="storeUpdater" xsi:type="string">Magento\Cms\Model\ResourceModel\Block\Relation\Store\SaveHandler</item>
                    </item>
                </item>
            </argument>
        </arguments>
    </type>

https://github.com/magento/magento2/blob/a74a8a82386589f9ed4d803d57edea874db8a822/app/code/Magento/Cms/Model/ResourceModel/Page/Relation/Store/SaveHandler.php#L46-L83

    public function execute($entity, $arguments = [])
    {
        $entityMetadata = $this->metadataPool->getMetadata(PageInterface::class);
        $linkField = $entityMetadata->getLinkField();

        $connection = $entityMetadata->getEntityConnection();

        $oldStores = $this->resourcePage->lookupStoreIds((int)$entity->getId());
        $newStores = (array)$entity->getStores();
        if (empty($newStores)) {
            $newStores = (array)$entity->getStoreId();
        }

        $table = $this->resourcePage->getTable('cms_page_store');

        $delete = array_diff($oldStores, $newStores);
        if ($delete) {
            $where = [
                $linkField . ' = ?' => (int)$entity->getData($linkField),
                'store_id IN (?)' => $delete,
            ];
            $connection->delete($table, $where);
        }

        $insert = array_diff($newStores, $oldStores);
        if ($insert) {
            $data = [];
            foreach ($insert as $storeId) {
                $data[] = [
                    $linkField => (int)$entity->getData($linkField),
                    'store_id' => (int)$storeId
                ];
            }
            $connection->insertMultiple($table, $data);
        }

        return $entity;
    }

Essentially PageInterface is linked to cms_page_store table

This might help

Magento 2 : extensionpool, read handlers and save handlers

1
  • Is there any other way that use single model instead of two. Same as like working module-cms Nov 12 '19 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.