0

I created a new table company_shipping_quote and new models by using https://mage2gen.com/.

But how can I create a new object and save it so that it appears in the database?

Models:

Company/Shipping/Model/Quote:

<?php
/**
 * Copyright ©  All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Company\Shipping\Model;

use Company\Shipping\Api\Data\QuoteInterface;
use Company\Shipping\Api\Data\QuoteInterfaceFactory;
use Magento\Framework\Api\DataObjectHelper;

class Quote extends \Magento\Framework\Model\AbstractModel
{

    protected $quoteDataFactory;

    protected $dataObjectHelper;

    protected $_eventPrefix = 'company_shipping_quote';

    /**
     * @param \Magento\Framework\Model\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param QuoteInterfaceFactory $quoteDataFactory
     * @param DataObjectHelper $dataObjectHelper
     * @param \Company\Shipping\Model\ResourceModel\Quote $resource
     * @param \Company\Shipping\Model\ResourceModel\Quote\Collection $resourceCollection
     * @param array $data
     */
    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        QuoteInterfaceFactory $quoteDataFactory,
        DataObjectHelper $dataObjectHelper,
        \Company\Shipping\Model\ResourceModel\Quote $resource,
        \Company\Shipping\Model\ResourceModel\Quote\Collection $resourceCollection,
        array $data = []
    ) {
        $this->quoteDataFactory = $quoteDataFactory;
        $this->dataObjectHelper = $dataObjectHelper;
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);
    }

    /**
     * Retrieve quote model with quote data
     * @return QuoteInterface
     */
    public function getDataModel()
    {
        $quoteData = $this->getData();

        $quoteDataObject = $this->quoteDataFactory->create();
        $this->dataObjectHelper->populateWithArray(
            $quoteDataObject,
            $quoteData,
            QuoteInterface::class
        );

        return $quoteDataObject;
    }
}

Company/Shipping/Model/QuoteRepository:

<?php
/**
 * Copyright ©  All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Company\Shipping\Model;

use Company\Shipping\Api\Data\QuoteInterfaceFactory;
use Company\Shipping\Api\Data\QuoteSearchResultsInterfaceFactory;
use Company\Shipping\Api\QuoteRepositoryInterface;
use Company\Shipping\Model\ResourceModel\Quote as ResourceQuote;
use Company\Shipping\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory;
use Magento\Framework\Api\DataObjectHelper;
use Magento\Framework\Api\ExtensibleDataObjectConverter;
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
use Magento\Framework\Exception\CouldNotDeleteException;
use Magento\Framework\Exception\CouldNotSaveException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Reflection\DataObjectProcessor;
use Magento\Store\Model\StoreManagerInterface;

class QuoteRepository implements QuoteRepositoryInterface
{

    private $collectionProcessor;

    protected $resource;

    protected $quoteFactory;

    protected $dataQuoteFactory;

    protected $extensibleDataObjectConverter;
    protected $searchResultsFactory;

    protected $dataObjectProcessor;

    private $storeManager;

    protected $quoteCollectionFactory;

    protected $extensionAttributesJoinProcessor;

    protected $dataObjectHelper;


    /**
     * @param ResourceQuote $resource
     * @param QuoteFactory $quoteFactory
     * @param QuoteInterfaceFactory $dataQuoteFactory
     * @param QuoteCollectionFactory $quoteCollectionFactory
     * @param QuoteSearchResultsInterfaceFactory $searchResultsFactory
     * @param DataObjectHelper $dataObjectHelper
     * @param DataObjectProcessor $dataObjectProcessor
     * @param StoreManagerInterface $storeManager
     * @param CollectionProcessorInterface $collectionProcessor
     * @param JoinProcessorInterface $extensionAttributesJoinProcessor
     * @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
     */
    public function __construct(
        ResourceQuote $resource,
        QuoteFactory $quoteFactory,
        QuoteInterfaceFactory $dataQuoteFactory,
        QuoteCollectionFactory $quoteCollectionFactory,
        QuoteSearchResultsInterfaceFactory $searchResultsFactory,
        DataObjectHelper $dataObjectHelper,
        DataObjectProcessor $dataObjectProcessor,
        StoreManagerInterface $storeManager,
        CollectionProcessorInterface $collectionProcessor,
        JoinProcessorInterface $extensionAttributesJoinProcessor,
        ExtensibleDataObjectConverter $extensibleDataObjectConverter
    ) {
        $this->resource = $resource;
        $this->quoteFactory = $quoteFactory;
        $this->quoteCollectionFactory = $quoteCollectionFactory;
        $this->searchResultsFactory = $searchResultsFactory;
        $this->dataObjectHelper = $dataObjectHelper;
        $this->dataQuoteFactory = $dataQuoteFactory;
        $this->dataObjectProcessor = $dataObjectProcessor;
        $this->storeManager = $storeManager;
        $this->collectionProcessor = $collectionProcessor;
        $this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor;
        $this->extensibleDataObjectConverter = $extensibleDataObjectConverter;
    }

    /**
     * {@inheritdoc}
     */
    public function save(
        \Company\Shipping\Api\Data\QuoteInterface $quote
    ) {
        /* if (empty($quote->getStoreId())) {
            $storeId = $this->storeManager->getStore()->getId();
            $quote->setStoreId($storeId);
        } */

        $quoteData = $this->extensibleDataObjectConverter->toNestedArray(
            $quote,
            [],
            \Company\Shipping\Api\Data\QuoteInterface::class
        );

        $quoteModel = $this->quoteFactory->create()->setData($quoteData);

        try {
            $this->resource->save($quoteModel);
        } catch (\Exception $exception) {
            throw new CouldNotSaveException(__(
                'Could not save the quote: %1',
                $exception->getMessage()
            ));
        }
        return $quoteModel->getDataModel();
    }

    /**
     * {@inheritdoc}
     */
    public function get($quoteId)
    {
        $quote = $this->quoteFactory->create();
        $this->resource->load($quote, $quoteId);
        if (!$quote->getId()) {
            throw new NoSuchEntityException(__('Quote with id "%1" does not exist.', $quoteId));
        }
        return $quote->getDataModel();
    }

    /**
     * {@inheritdoc}
     */
    public function getList(
        \Magento\Framework\Api\SearchCriteriaInterface $criteria
    ) {
        $collection = $this->quoteCollectionFactory->create();

        $this->extensionAttributesJoinProcessor->process(
            $collection,
            \Company\Shipping\Api\Data\QuoteInterface::class
        );

        $this->collectionProcessor->process($criteria, $collection);

        $searchResults = $this->searchResultsFactory->create();
        $searchResults->setSearchCriteria($criteria);

        $items = [];
        foreach ($collection as $model) {
            $items[] = $model->getDataModel();
        }

        $searchResults->setItems($items);
        $searchResults->setTotalCount($collection->getSize());
        return $searchResults;
    }

    /**
     * {@inheritdoc}
     */
    public function delete(
        \Company\Shipping\Api\Data\QuoteInterface $quote
    ) {
        try {
            $quoteModel = $this->quoteFactory->create();
            $this->resource->load($quoteModel, $quote->getQuoteId());
            $this->resource->delete($quoteModel);
        } catch (\Exception $exception) {
            throw new CouldNotDeleteException(__(
                'Could not delete the Quote: %1',
                $exception->getMessage()
            ));
        }
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function deleteById($quoteId)
    {
        return $this->delete($this->get($quoteId));
    }
}

Company/Shipping/Model/Data/Quote.php:

<?php
/**
 * Copyright ©  All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Company\Shipping\Model\Data;

use Company\Shipping\Api\Data\QuoteInterface;

class Quote extends \Magento\Framework\Api\AbstractExtensibleObject implements QuoteInterface
{

    /**
     * Get quote_id
     * @return string|null
     */
    public function getQuoteId()
    {
        return $this->_get(self::QUOTE_ID);
    }

    /**
     * Set quote_id
     * @param string $quoteId
     * @return \Company\Shipping\Api\Data\QuoteInterface
     */
    public function setQuoteId($quoteId)
    {
        return $this->setData(self::QUOTE_ID, $quoteId);
    }

    /**
     * Get id
     * @return string|null
     */
    public function getId()
    {
        return $this->_get(self::ID);
    }

    /**
     * Set id
     * @param string $id
     * @return \Company\Shipping\Api\Data\QuoteInterface
     */
    public function setId($id)
    {
        return $this->setData(self::ID, $id);
    }

    /**
     * Retrieve existing extension attributes object or create a new one.
     * @return \Company\Shipping\Api\Data\QuoteExtensionInterface|null
     */
    public function getExtensionAttributes()
    {
        return $this->_getExtensionAttributes();
    }

    /**
     * Set an extension attributes object.
     * @param \Company\Shipping\Api\Data\QuoteExtensionInterface $extensionAttributes
     * @return $this
     */
    public function setExtensionAttributes(
        \Company\Shipping\Api\Data\QuoteExtensionInterface $extensionAttributes
    ) {
        return $this->_setExtensionAttributes($extensionAttributes);
    }

    /**
     * Get express_note
     * @return string|null
     */
    public function getExpressNote()
    {
        return $this->_get(self::EXPRESS_NOTE);
    }

    /**
     * Set express_note
     * @param string $expressNote
     * @return \Company\Shipping\Api\Data\QuoteInterface
     */
    public function setExpressNote($expressNote)
    {
        return $this->setData(self::EXPRESS_NOTE, $expressNote);
    }
}

Company/Shipping/Model/ResourceModel/Quote.php:

<?php
/**
 * Copyright ©  All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Company\Shipping\Model\ResourceModel;

class Quote extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{

    /**
     * Define resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('company_shipping_quote', 'quote_id');
    }
}

Company/Shipping/Model/ResourceModel/Quote/Collection.php:

<?php
/**
 * Copyright ©  All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Company\Shipping\Model\ResourceModel\Quote;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{

    /**
     * @var string
     */
    protected $_idFieldName = 'quote_id';

    /**
     * Define resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init(
            \Company\Shipping\Model\Quote::class,
            \Company\Shipping\Model\ResourceModel\Quote::class
        );
    }
}

Database

enter image description here

Company/Shipping/etc/db_schema.xml:

<?xml version="1.0"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="company_shipping_quote" resource="default">
        <column xsi:type="int" name="id" nullable="false" unsigned="true" comment="ID"/>
        <constraint xsi:type="primary" referenceId="PRIMARY">
            <column name="id"/>
        </constraint>

        <column xsi:type="int" name="quote_id" nullable="false" unsigned="true" comment="Quote ID"/>
<!--        <constraint xsi:type="foreign"
                    referenceId="FK_QUOTE_ENTITIY_ID"
                    table="company_shipping_quote"
                    column="quote_id"
                    referenceTable="quote"
                    referenceColumn="entity_id"
                    onDelete="CASCADE"/>-->

        <column xsi:type="text" name="express_note" nullable="true" comment="Express Shipping Note with Additional Information"/>
    </table>
</schema>

Of course I executed bin/magento setup:upgrade && bin/magento setup:di:compile

Attempt:

Now inside another class I tried to create an object of the model and save it:

protected $_companyShippingQuoteFactory;

public function __construct(
    ...
    \Company\Shipping\Model\QuoteFactory $companyShippingQuoteFactory
) {
    ...
    $this->_companyShippingQuoteFactory = $companyShippingQuoteFactory;
}

...

$quoteModel = $this->_companyShippingQuoteFactory->create();
$quoteModel->setQuoteId(123);
$quoteModel->setExpressNote("foo_bar");
$quoteModel->save();

But it does not save. The database table is still empty:

enter image description here

1

It might be related to your: db_schema.xml

Try to add:

 <column xsi:type="int" name="id" nullable="false" unsigned="true" comment="ID" identity="true"/>

Adding identity="true"

If you check e.g. this example you see they have it on their primary key:

https://devdocs.magento.com/guides/v2.4/extension-dev-guide/declarative-schema/db-schema.html

0
0

I figured it out. It was not saving because the mage2gen generator added wrong values for the ID in the files, because my table name ends with _quote and it took it to make quote_id to the ID key..., but I am already using quote_id as a field, so it does not work out...

  • Company/Shipping/Model/ResourceModel/Quote/Collection.php
  • Company/Shipping/Model/ResourceModel/Quote.php

I also have set identity='true' like @Kristoffer suggested.

1
  • I double checked it, and it was indeed the reason. I also set identity='true' like @Kristoffer suggested. – Black Oct 21 '20 at 10:55

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.