6

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.

  • Are getStoreId return array? 8| – KAndy Jun 14 '16 at 18:54
  • Yes, getStoreId will return an array. The ids of the stores associated to my entity. – Marius Jun 14 '16 at 19:15
4

Magento service layers support only homogeneous arrays.

So you cannot define type as just array. You should define it as TypeName[], for example int[].

| improve this answer | |
  • I see. I will give it a try tomorrow morning. – Marius Jun 14 '16 at 19:16

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.