Magento 2 – Custom Model with EAV Attributes, PUT Not Working

apicustomeavmagento2module

I'm trying to figure out how works EAV attributes. So I made a simple example with API rest. Everything is working except when I call PUT function:

{
    "sample" : {
        "id": 22,
        "name": "Sample 22"
    }
}

{
"message": "Could not save sample: %1",
"parameters": [
    "SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE (`entity_id`=22)' at line 1, query was: UPDATE `sample_entity` SET  WHERE (`entity_id`=22)"
],
"trace": "..."

}

It's like it can't figure out how to update the attribute name, but when I call a POST for creating a new Sample it creates it right.

I did it that example based on these other example repositories:

The model is that simple:

  • id (sample_entity)
  • name (sample_entity_varchar)

Posting some code (request something if you need it) I have no idea what I missed neither where it can be:

etc/webapi.xml

<route url="/V1/gsp/sample" method="POST">
    <service class="Gsp\Test\Api\SampleRepositoryInterface" method="save"/>
    <resources>
        <resource ref="Magento_Backend::admin"/>
    </resources>
</route>

<route url="/V1/gsp/sample" method="PUT">
    <service class="Gsp\Test\Api\SampleRepositoryInterface" method="save"/>
    <resources>
        <resource ref="Magento_Backend::admin"/>
    </resources>
</route>

Model/SampleRepository.php

public function save(\Gsp\Test\Api\Data\SampleInterface $sample)
{
    try {
        $this->resourceModel->save($sample);
    } catch (\Exception $e) {
        throw new \Magento\Framework\Exception\CouldNotSaveException(
            __(
                'Could not save sample: %1',
                $e->getMessage()
            ),
            $e
        );
    }
    unset($this->instances[$sample->getId()]);
    return $sample;
}

Api/Data/SampleInterface.php

<?php

namespace Gsp\Test\Api\Data;

/**
 * @api
 */
interface SampleInterface extends \Magento\Framework\Api\CustomAttributesDataInterface
{
    /**#@+
     * Constants defined for keys of  data array
     */
    const ID = 'id';
    const NAME = 'name';
    /**#@-*/

    /**
     * @return int|null
     */
    public function getId();

    /**
     * @param int $id
     * @return $this
     */
    public function setId($id);

    /**
     * Get category name
     *
     * @return string
     */
    public function getName();

    /**
     * Set category name
     *
     * @param string $name
     * @return $this
     */
    public function setName($name);
}

Best Answer

The problem was, I missed to define the attributes on the setup. In detail:

public function getDefaultEntities()
{
    return [
        'gsp_sample' => [
            'entity_model' => 'Gsp\Test\Model\ResourceModel\Sample',
            'attribute_model' => 'Magento\Catalog\Model\ResourceModel\Eav\Attribute',
            'table' => 'gsp_sample',
            'entity_attribute_collection' => 'Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection',
            'attributes' => [
                'name' => [
                    'type' => 'varchar',
                    'label' => 'Name',
                    'source' => 'Gsp\Test\Model\Product\Attribute\Source\Sample',
                    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_STORE,
                ],
            ],
        ]
    ];
}