Unikanie zapisu w pętli w akcji masowej

13

Stworzyłem własny moduł CRUD, który zawiera wbudowaną akcję edycyjną podobną do tej dla stron CMS.
Wszystko działa OK, ale kiedy uruchamiam phpsniffer ze standardem EcgM2 , otrzymuję to ostrzeżenie:

Modelowa metoda LSD save () wykryta w pętli

Jak mogę tego uniknąć?
Uwaga: to samo ostrzeżenie pojawia się, gdy „powącham” plik podstawowy, do którego odsyłam powyżej.
Oto moja executemetoda na wypadek, gdyby ktoś jej potrzebował. Ale jest bardzo podobny do tego z kontrolera strony 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
    ]);
}
Marius
źródło

Odpowiedzi:

5

W takim przypadku musisz do save()swoich bytów, więc na pewno będziesz musiał wywołać tę metodę.

Natywny główny plik Magento, który podłączyłeś, nie jest jedynym, który to robi, szczególnie klasy akcji masowych akcji.

Jedyną alternatywą jest dodanie saveAttributemetody do modelu zasobów CRUD w oparciu o ten zaimplementowany w 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;
}

W ten sposób zamiast wywoływać:

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

Powinieneś być w stanie zrobić coś takiego:

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

Jak stwierdzono w komentarzach, musisz nieco zmodyfikować tę metodę, jeśli nie musisz sprawdzać AbstractAttributeinstancji, aby dopasować ją do swoich potrzeb

Raphael at Digital Pianism
źródło
Szwy rozsądne. dzięki. Spróbuję i wrócę z wynikami.
Marius
@Marius pamiętaj, że ta metoda różni się nieco od saveAttributemetody EAV , ponieważ akceptuje tablicę „kodów atrybutów” do zapisania zamiast jednego kodu atrybutu
Raphael at Digital Pianism
1
Zauważyłem to. Nawet go trochę zmodyfikowałem, aby nie akceptował i wystąpił AbstractAttributejako parametr, ponieważ nie potrzebuję go w mojej płaskiej jednostce. Działa płynnie. Dzięki jeszcze raz.
Marius