Éviter de sauvegarder dans une boucle en action de masse


13

J'ai créé mon propre module CRUD qui contient une action d'édition en ligne similaire à celle des pages CMS
Tout fonctionne bien, mais lorsque je lance phpsniffer avec la norme EcgM2, j'obtiens cet avertissement:

La méthode modèle LSD save () détectée en boucle

Comment puis-je éviter ça?
Remarque: le même avertissement apparaît si je "renifle" le fichier principal lié ci-dessus.
Voici ma executeméthode au cas où quelqu'un en aurait besoin. Mais il est très similaire à celui du contrôleur de page 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
    ]);
}

Réponses:


5

Dans ce cas, vous devez accéder à save()vos entités, vous devrez donc certainement appeler cette méthode.

Le fichier natif Magento de base que vous avez lié n'est pas le seul à le faire, en particulier les classes d'actions d'actions de masse.

La seule alternative consiste à ajouter une saveAttributeméthode à votre modèle de ressource CRUD basée sur celle implémentée dans 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;
}

De cette façon, au lieu d'appeler ce qui suit:

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

Vous devriez pouvoir faire quelque chose comme ceci:

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

Comme indiqué dans les commentaires, vous devrez modifier un peu cette méthode si vous n'avez pas besoin de vérifier l' AbstractAttributeinstance pour répondre à vos besoins


Coutures raisonnables. Merci. Je vais essayer et je reviendrai avec les résultats.
Marius

@Marius gardez juste à l'esprit que cette méthode est légèrement différente de la saveAttributeméthode EAV car elle accepte un tableau de "codes d'attribut" à enregistrer au lieu d'un seul code d'attribut
Raphael au Digital Pianism

1
Je l'ai remarqué. Je l'ai même un peu modifié pour qu'il n'accepte pas et comme instance de AbstractAttributeparamètre, car je n'en ai pas besoin dans mon entité plate. Cela fonctionne bien. Merci encore.
Marius
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.