Vermeiden Sie das Speichern in einer Schleife in Massenaktionen

12

Ich habe mein eigenes CRUD-Modul erstellt, das eine Inline-Bearbeitungsaktion ähnlich der für CMS-Seiten enthält.
Alles funktioniert in Ordnung, aber wenn ich phpsniffer mit dem EcgM2-Standard ausführe , wird folgende Warnung angezeigt :

Modell LSD-Methode save () in Schleife erkannt

Wie kann ich das vermeiden?
Hinweis: Die gleiche Warnung wird angezeigt, wenn ich an der oben verlinkten Kerndatei "schnüffle".
Hier ist meine executeMethode für den Fall, dass jemand sie braucht. Aber es ist dem des CMS-Seitencontrollers sehr ähnlich

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

Antworten:

5

In diesem Fall müssen Sie save()Ihre Entitäten, also müssen Sie diese Methode definitiv aufrufen.

Die native Magento-Kerndatei, die Sie verlinkt haben, ist nicht die einzige, die dies tut, insbesondere die Aktionsklassen für Massenaktionen.

Die einzige Alternative besteht darin saveAttribute, Ihrem CRUD-Ressourcenmodell eine Methode hinzuzufügen, die auf der folgenden Methode basiert 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;
}

Auf diese Weise, anstatt Folgendes aufzurufen:

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

Sie sollten in der Lage sein, so etwas zu tun:

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

Wie in den Kommentaren angegeben, müssen Sie diese Methode ein wenig ändern, wenn Sie die AbstractAttributeInstanz nicht auf Ihre Anforderungen überprüfen müssen

Raphael beim digitalen Pianismus
quelle
Nähte vernünftig. Vielen Dank. Ich werde es versuchen und mit den Ergebnissen zurückkommen.
Marius
@Marius denken Sie nur daran, dass diese Methode etwas anders ist als die EAV- saveAttributeMethode, da sie ein Array von "Attributcodes" zum Speichern anstelle von nur einem Attributcode akzeptiert
Raphael bei Digital Pianism
1
Ich habe das bemerkt. Ich habe es sogar ein wenig geändert, damit es keine Instanz AbstractAttributeals Parameter akzeptiert , da ich es in meiner flachen Entität nicht benötige. Es funktioniert reibungslos. Danke noch einmal.
Marius