I'm trying to build a proper CRUD module for Magento 2.
My module contains for now an entity called Author
.
This module contains the main entity table and a many to many relations table with the store views (similar to the cms pages and static blocks).
I've created, among others, an interface for the main model called [Namespace]\[Module]\Api\Data\AuthorInterface
following the same guidelines as for CMS pages.
interface AuthorInterface extends ExtensibleDataInterface
{
const AUTHOR_ID = 'author_id';
const NAME = 'name';
const STORE_ID = 'store_id'; //this is missing in the cms page interface
/**
* Get ID
*
* @return int|null
*/
public function getId();
/**
* Get name
*
* @return string
*/
public function getName();
/**
* set id
*
* @param $id
* @return AuthorInterface
*/
public function setId($id);
/**
* set name
*
* @param $name
* @return AuthorInterface
*/
public function setName($name);
/**
* @param $storeId
* @return AuthorInterface
*/
public function setStoreId($storeId);
/**
* @return array
*/
public function getStoreId();
}
Now here come the differences and problems.
The cms page interface does not contain the constant STORE_ID
nor the methods setStoreId
or getStoreId
.
But from my point of view they should be there.
Also the cms pages save action uses the $page->save()
call that is deprecated.
I decided to use repositories.
So my save action looks something like this:
$data = $this->getRequest()->getPostValue();
....
$author->setName($data['name']);//don't worry, I have a verification for the existence of $data['name']
$author->setStoreId($data['store_id']);
$this->authorRepository->save($author); //authorRepository is an instance of \[Namespace]\[Module]\Api\AuthorRepositoryInterface
This works nicely, but what if my entity has a lot of fields, not just a name?
I don't want to call ->set...
a hundred times. Plus, if I add one more field, I need to modify my code.
I discovered the method \Magento\Framework\Api\DataObjectHelper::populateWithArray
.
Now I can simply call
$this->dataObjectHelper->populateWithArray($author, $data , '\[Namespace]\[Module]\Api\Data\AuthorInterface'); //where dataObjectHelper is an instance of \Magento\Framework\Api\DataObjectHelper
This, again, works flawlessly except for the store_id
.
I get an exception Class array does not exist
because the annotation for getStoreId
says @return array
. can confirm that changing this annotation changes the exception message or works when changing the return type to string
. But my store id is going to be an array not a string.
What is the proper way to handle this kind of case?
[EDIT]
I could go around this by using
$data = $this->getRequest()->getPostValue();
...
if (isset($data['store_id'])) {
$author->setStoreId($data['store_id']);
unset($data['store_id']);
}
$this->dataObjectHelper->populateWithArray($author, $data , '\[Namespace]\[Module]\Api\Data\AuthorInterface');
But this looks dirty.
Best Answer
Magento service layers support only homogeneous arrays.
So you cannot define type as just array. You should define it as TypeName[], for example int[].