I am trying to create a module that uploads Category image (as Category extension attribute) via REST API. The problem is that I can’t even fetch extension attributes in afterSave method of my Plugin with the lines of code below:
$extensionAttributes = $category->getExtensionAttributes() ?: $this->categoryExtensionFactory->create();
And then, can’t save this attribute in my custom table due to Integrity constraint violation (beause my extension attribute has NULL value):
[2022-09-20 00:21:02] main.ERROR: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'api_uploaded_image' cannot be null, query was: INSERT INTO `sl_category_image_via_api_attribute` (`category_id`, `api_uploaded_image`) VALUES (?, ?) [] []
Though, obviously, extension attribute is set in my API request to
https://{{magento2_root}}/rest/async/bulk/V1/categories
{
"id": 352,
"parent_id": 229,
"name": "Мобільний телефон Nokia 108100",
"is_active": true,
"position": 1,
"level": 4,
"children": "",
"created_at": "2022-09-18 18:48:16",
"updated_at": "2022-09-18 18:48:16",
"path": "1/2/161/229/352",
"available_sort_by": [],
"include_in_menu": true,
"extension_attributes": {
"api_uploaded_image": "YnsA"
},
.
.
.
}
1. 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="sl_category_image_via_api_attribute" resource="default" engine="innodb" comment="Category Images Sent Via API Table">
<column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" identity="true" comment="Entity ID"/>
<column xsi:type="int" name="category_id" padding="10" unsigned="true" nullable="false" identity="false" comment="Category ID"/>
<column xsi:type="varchar" name="api_uploaded_image" nullable="false" comment="Base64 Encoded Images"/>
<column xsi:type="timestamp" name="created_at" on_update="false" nullable="false" default="CURRENT_TIMESTAMP" comment="Create Time"/>
<column xsi:type="timestamp" name="updated_at" on_update="true" nullable="false" default="CURRENT_TIMESTAMP" comment="Update Time"/>
<constraint xsi:type="primary" referenceId="PRIMARY">
<column name="entity_id"/>
</constraint>
<constraint xsi:type="foreign" referenceId="SL_CTGRY_IMG_VIA_API_ATTR_CATEGORY_ID_CATALOG_CTGRY_ENTT_ENTT_ID"
table="sl_category_image_via_api_attribute" column="category_id" referenceTable="catalog_category_entity"
referenceColumn="entity_id" onDelete="CASCADE"/>
</table>
</schema>
In a case I set nullable=”true” for name=”api_uploaded_image” attribute in db_schema.xml:
<column xsi:type="varchar" name="api_uploaded_image" nullable="true" comment="Base64 Encoded Images"/>
then I can save my custom entity in a custom table with “api_uploaded_image” column and NULL value:
How can I retrive category extension attribute in a Plugin (afterSave method) and then save it to my custom table?
I will be appreciate for your help.
Thanks in advance.
2. The full code of Plugin
<?php
declare(strict_types=1);
namespace SlCategoryImageApiUploadPlugin;
use MagentoCatalogApiDataCategoryExtensionFactory;
use SlCategoryImageApiUploadApiManagementInterface;
use MagentoCatalogApiDataCategoryInterface;
use MagentoCatalogApiDataCategorySearchResultsInterface;
use MagentoCatalogApiCategoryRepositoryInterface;
use SlCategoryImageApiUploadModelAttributesFactory;
use SlCategoryImageApiUploadModelAttributesResource;
use PsrLogLoggerInterface;
class CategoryRepositoryPlugin
{
/**
* @var LoggerInterface
*/
private LoggerInterface $logger;
/**
* @var ManagementInterface
*/
private ManagementInterface $management;
/**
* @var AttributesFactory
*/
private AttributesFactory $attributesFactory;
/**
* @var AttributesResource
*/
private AttributesResource $attributesResource;
/**
* @var CategoryExtensionFactory
*/
private CategoryExtensionFactory $categoryExtensionFactory;
/**
* CategoryRepositoryPlugin constructor.
* @param AttributesFactory $attributesFactory
* @param AttributesResource $attributesResource
* @param ManagementInterface $management
* @param CategoryExtensionFactory $categoryExtensionFactory
*/
public function __construct(
AttributesFactory $attributesFactory,
AttributesResource $attributesResource,
CategoryExtensionFactory $categoryExtensionFactory,
ManagementInterface $management,
LoggerInterface $logger
) {
$this->attributesFactory = $attributesFactory;
$this->attributesResource = $attributesResource;
$this->categoryExtensionFactory = $categoryExtensionFactory;
$this->management = $management;
$this->logger = $logger;
}
/**
* @param CategoryRepositoryInterface $subject
* @param CategorySearchResultsInterface $categorySearchResult
* @return CategorySearchResultsInterface
*/
public function afterGetList(
CategoryRepositoryInterface $subject,
CategorySearchResultsInterface $categorySearchResult
): CategorySearchResultsInterface {
foreach ($categorySearchResult->getItems() as $category) {
$this->afterGet($subject, $category);
}
return $categorySearchResult;
}
/**
* @param CategoryRepositoryInterface $subject
* @param CategoryInterface $category
* @return CategoryInterface
*/
public function afterGet(
CategoryRepositoryInterface $subject,
CategoryInterface $category
): CategoryInterface {
$categoryAttribute = $this->management->getByCategoryId((int) $category->getId());
$extensionAttributes = $category->getExtensionAttributes();
$extensionAttributes->setCategoryId($categoryAttribute->getCategoryId());
$extensionAttributes->setApiUploadedImage($categoryAttribute->getApiUploadedImage());
$category->setExtensionAttributes($extensionAttributes);
return $category;
}
/**
* @param CategoryRepositoryInterface $subject
* @param CategoryInterface $category
* @return CategoryInterface
*/
public function afterSave(
CategoryRepositoryInterface $subject,
CategoryInterface $category
): CategoryInterface {
// $categoryAttribute = $this->management->getByCategoryId((int) $category->getId());
// $categoryCollection = $this->categoryFactory->create()->getAttributesCollection();
$extensionAttributes = $category->getExtensionAttributes() ?: $this->categoryExtensionFactory->create();
if ($extensionAttributes !== null && $extensionAttributes->getApiUploadedImage() !==null) {
// $extensionAttributes->setApiUploadedImage($extensionAttributes->getApiUploadedImage());
$attributesEntity = $this->attributesFactory->create();
$attributesEntity->setCategoryId($category->getId());
$attributesEntity->setApiUploadedImage($extensionAttributes->getApiUploadedImage());
// $this->logger->debug('valuer=' .serialize($attributesEntity));
$this->management->save($attributesEntity);
// $this->attributesRepository->save($attributesEntity);
// $this->$subject->save();
}
// $extensionAttributes->setCategoryId($categoryAttribute->getCategoryId());
// $extensionAttributes->setApiUploadedImage($categoryAttribute->getApiUploadedImage());
// $category->setExtensionAttributes($extensionAttributes);
return $category;
}
}