13

I've created my own CRUD module that contains an inline edit action similar to the one for CMS pages
Everything works OK, but when running phpsniffer with the EcgM2 standard I get this warning:

Model LSD method save() detected in loop

How can I avoid this?
Note: The same warning appears if I "sniff" the core file linked above.
Here is my execute method in case someone needs it. But it's very similar to the one from the CMS page controller

public function execute()
{
    /** @var \Magento\Framework\Controller\Result\Json $resultJson */
    $resultJson = $this->jsonFactory->create();
    $error = false;
    $messages = [];

    $postItems = $this->getRequest()->getParam('items', []);
    if (!($this->getRequest()->getParam('isAjax') && count($postItems))) {
        return $resultJson->setData([
            'messages' => [__('Please correct the data sent.')],
            'error' => true,
        ]);
    }

    foreach (array_keys($postItems) as $authorId) {
        /** @var \Sample\News\Model\Author $author */
        $author = $this->authorRepository->getById((int)$authorId);
        try {
            $authorData = $this->filterData($postItems[$authorId]);
            $this->dataObjectHelper->populateWithArray($author, $authorData , AuthorInterface::class);
            $this->authorRepository->save($author);
        } catch (LocalizedException $e) {
            $messages[] = $this->getErrorWithAuthorId($author, $e->getMessage());
            $error = true;
        } catch (\RuntimeException $e) {
            $messages[] = $this->getErrorWithAuthorId($author, $e->getMessage());
            $error = true;
        } catch (\Exception $e) {
            $messages[] = $this->getErrorWithAuthorId(
                $author,
                __('Something went wrong while saving the author.')
            );
            $error = true;
        }
    }

    return $resultJson->setData([
        'messages' => $messages,
        'error' => $error
    ]);
}
5

In that case you have to save() your entities, so you'll definitely have to call that method.

The native core Magento file you linked is not the only one that does that, especially the mass actions action classes.

The only alternative is to add a saveAttribute method to your CRUD resource model based on the one implemented in app/code/Magento/Sales/Model/ResourceModel/Attribute.php :

public function saveAttribute(AbstractModel $object, $attribute)
{
    if ($attribute instanceof AbstractAttribute) {
        $attributes = $attribute->getAttributeCode();
    } elseif (is_string($attribute)) {
        $attributes = [$attribute];
    } else {
        $attributes = $attribute;
    }
    if (is_array($attributes) && !empty($attributes)) {
        $this->getConnection()->beginTransaction();
        $data = array_intersect_key($object->getData(), array_flip($attributes));
        try {
            $this->_beforeSaveAttribute($object, $attributes);
            if ($object->getId() && !empty($data)) {
                $this->getConnection()->update(
                    $object->getResource()->getMainTable(),
                    $data,
                    [$object->getResource()->getIdFieldName() . '= ?' => (int)$object->getId()]
                );
                $object->addData($data);
            }
            $this->_afterSaveAttribute($object, $attributes);
            $this->getConnection()->commit();
        } catch (\Exception $e) {
            $this->getConnection()->rollBack();
            throw $e;
        }
    }
    return $this;
}

This way, instead of calling the following:

$this->authorRepository->save($author);

You should be able to do something like this:

$author->getResource()->saveAttribute($author, array_keys($authorData));

As stated in the comments, you'll have to modify that method a bit if you don't need to check the AbstractAttribute instance to match your needs

| improve this answer | |
  • Seams reasonable. thanks. I'll give it a shot and come back with the results. – Marius Jul 1 '16 at 8:20
  • @Marius just keep in mind that this method is slightly different than the EAV saveAttribute method as it accepts an array of "attribute codes" to save instead of just one attribute code – Raphael at Digital Pianism Jul 1 '16 at 8:22
  • 1
    I've noticed that. I even modified it a bit so it won't accept and instance of AbstractAttribute as parameter, because I don't need it in my flat entity. It works smoothly. Thanks again. – Marius Jul 1 '16 at 8:45

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.