避免在大规模动作中循环保存


13

我创建了自己的CRUD模块,其中包含类似于CMS页面的内联编辑操作,
一切正常,但是以EcgM2标准运行phpsniffer时,出现以下警告:

在循环中检测到模型LSD方法save()

如何避免这种情况?
注意:如果我“嗅探”上面链接的核心文件,则会出现相同的警告。如果有人需要,
这是我的execute方法。但这与CMS页面控制器中的非常相似

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
    ]);
}

Answers:


5

在这种情况下,您必须对save()实体进行操作,因此绝对必须调用该方法。

您链接的本机核心Magento文件不是唯一执行此操作的文件,尤其是大规模动作动作类。

唯一的选择是saveAttribute根据在中实现的方法,将一种方法添加到您的CRUD资源模型中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->authorRepository->save($author);

您应该能够执行以下操作:

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

如评论中所述,如果您不需要检查AbstractAttribute实例以满足您的需要,则必须对该方法进行一些修改


接缝合理。谢谢。我会试一试,然后返回结果。
马吕斯

@Marius请记住,此方法与EAV saveAttribute方法略有不同,因为它接受保存的一组“属性代码”而不是仅保存一个属性代码
Raphael在Digital Pianism '16

1
我注意到了。我什至对其做了一些修改,因此它不会接受AbstractAttributeas的实例和as参数,因为在我的平面实体中不需要它。它工作顺利。再次感谢。
Marius
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.