Wie soll ich neue oder aktualisierte Entitäten von Modellen speichern?

10

In Magento 2 haben wir Repositorys-Klassen. Die save()in Magento 1.9 häufig verwendete klassische Methode ist , wenn ich richtig bin, von 2.04 oder 2.05 veraltet. Ich habe Fabriken verwendet, um ein neues Objekt zu erstellen, und nachdem ich die Eigenschaften von new festgelegt habe, zum Beispiel das Produkt, das ich aufgerufen habe save():

$productFactory->create()->setName()...->save()

Auf der anderen Seite haben wir Repositorys, die auch Methoden enthalten save. Ich benutze es auf den Punkt gebracht:

$product = $productFactory->create()->setName()... $productRepository->save($product)

In meinem Code arbeiten Klassen in beide Richtungen. Mir ist auch aufgefallen, dass manchmal unterschiedliche Wege unterschiedliches Verhalten bedeuten. Hat der Weg mit Repositories eine zusätzliche Validierung der bereitgestellten Daten?

Wie soll ich das machen?

Bartosz Kubicki
quelle

Antworten:

10

Lassen Sie uns zunächst sehen, was passiert, wenn Sie die save()Methode direkt auf einem productModell wie verwenden

/**
 * @var Magento\Catalog\Model\Product $product
 */
$product->save();

Die Modellklasse selbst ist

Magento\Catalog\Model\Product

Suchen Sie innerhalb dieser Klasse nach der Definition der save () -Methode.

Keiner richtig gefunden? Nun, es gibt beforeSave () und afterSave (), aber nicht save () selbst. Interessant, nein?

Dann müssen wir uns die übergeordneten Klassen von ansehen Magento\Catalog\Model\Product.

Wir müssen durch Magento\Catalog\Model\AbstractModelund Magento\Framework\Model\AbstractExtensibleModel, nur um endlich zu erreichen Magento\Framework\Model\AbstractModel.

Sicher genug, hier gibt es eine save () -Methode, die ungefähr so ​​aussieht

public function save()
{
    $this->_getResource()->save($this);
    return $this;
}

Wir sehen jetzt, wann immer save () für ein Modell aufgerufen wird, die save () -Methode von diesem AbstractModelaufgerufen wird, und die Implementierung besteht darin, dass das RESOURCE-MODELL tatsächlich das Speichern durchführt.

Letzteres ist nicht überraschend, da wir immer, wie von Anfang an in Magento 1.0, sowohl ein Modell als auch ein Ressourcenmodell für nahezu jede Entität erstellen.


Schauen wir uns nun an, wie das ProductRepositoryfunktioniert.

Lässt die Datei öffnen

/vendor/magento/module-catalog/Api/ProductRepositoryInterface.php

Diese Schnittstelle erfordert unter anderem eine save () -Methode.

Wer implementiert diese Schnittstelle tatsächlich?

Lässt die Datei öffnen

/etc/di.xml

und überprüfen Sie Zeile 10

<preference for="Magento\Catalog\Api\ProductRepositoryInterface" type="Magento\Catalog\Model\ProductRepository" />

Natürlich finden wir die Implementierung des save () menthod im Inneren

/vendor/magento/module-catalog/Model/ProductRepository

und es beginnt in Zeile 444 und sieht ungefähr so ​​aus

public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveOptions = false)
{
    $tierPrices = $product->getData('tier_price');

    try {
    .... other code here ....

Diese Methode erwartet, dass ein $ product-Objekt vom Typ \Magento\Catalog\Api\Data\ProductInterfaceübergeben wird, das jedoch standardmäßig in aufgelöst wird Magento\Catalog\Model\Product.

Wenn trywir in Zeile 500 nach unten schauen , sehen wir in einer Aussage so etwas wie

$this->resourceModel->save($product);

Du hast es gut erraten! $this->resourceModelist vom Typ \Magento\Catalog\Model\ResourceModel\Product, protectedin Zeile 77 als Eigenschaft deklariert .

Also wieder macht das ResourceModeltatsächlich das Sparen.

Aber zwischen Zeile 444 und 500 ist tatsächlich die Antwort auf Ihre Frage. Der gesamte hier ausgeführte Code kann und wird möglicherweise zu Verhaltensunterschieden zwischen dem direkten Speichern des Modells und dieser Art des Speicherns im Repository führen.

Zum Beispiel wird das Produkt-Repository Produktlinks abrufen und verarbeiten, wenn das auf gesetzt ignore_links_flagist 0, prüfen, ob es sich überhaupt um ein vorhandenes Produkt handelt usw.

Wir müssen wahrscheinlich zu dem Schluss kommen, dass, wenn in Zukunft geändert werden muss, wie das Produkt gespeichert wird, der bessere Weg, dies zu tun, möglicherweise darin besteht, das Produkt-Repository anstelle des Produktmodells zu überschreiben.

Gleiches gilt für das Speichern und Aktualisieren von Produkten. Ich würde lieber das Produkt-Repository-Objekt verwenden.

Ich verweise Sie auch freundlicherweise auf /vendor/magento/module-cms/Model/PageRepository.php

Auf diese Weise würde eine CMS-Seite über das Repository gespeichert. Hier ist es einfacher. Die Geschäfts-ID wird festgelegt und das Ressourcenmodell wird aufgerufen, um sofort zu speichern.

Mit dieser letzten Mitteilung werden Sie zu dem Schluss kommen, dass es in einigen Fällen möglicherweise nicht so viele Unterschiede zwischen Repository und Modellspeicherung gibt, aber ich hoffe trotzdem, dass Sie jetzt in der Lage sind, sie zu erkennen, wann immer Sie dies benötigen.

Marjan
quelle
1

Es wird empfohlen, Datenschnittstellen (z. B. \Magento\Catalog\Api\Data\ProductInterface) anstelle des Modells direkt zu verwenden und die Repositorys zum Laden und Speichern von Modellen zu verwenden.

Siehe Magento Entwickler - Dokumentation

ochnygosch
quelle
1
ok - das ist der richtige Weg für die gesamte Entität - aber nur um den Wert eines Attributs zu aktualisieren - ich denke, das Laden / Speichern der gesamten Entität wird nicht empfohlen.
Bartosz Kubicki