Gibt es jemals einen Grund, $ model-> load () Serviceverträgen vorzuziehen?

24

Ich verstehe, dass die bevorzugte Art, in Magento 2 zwischen Modulen zu arbeiten, die Verwendung von Serviceverträgen ist.

Wenn ich also ein Produkt laden möchte, verwende ich das Produkt-Repository:

$product = $productRepository->getById($id);

Das ist vertraglich die Rückgabe einer Instanz von Magento\Catalog\Api\Data\ProductInterface.

Aber ich könnte stattdessen auch den alten Weg verwenden und die Domain-Ebene direkt aufrufen:

$product = $productFactory->create()->load($id);

Gibt es einen Fall, in dem dies notwendig oder nützlich wäre?

Die Devdocs sagen (Highlight hinzugefügt):

Ein Modul kann direkt in ein anderes Modul aufrufen. Diese eng gekoppelte Lösung wird für die meisten Situationen nicht empfohlen, ist jedoch manchmal unvermeidlich .

[...]

Ihre Strategie zum Aufrufen des Domain-Layer-Codes eines anderen Moduls hängt stark von der Konfiguration und den Anforderungen Ihres Systems ab.

Quelle: http://devdocs.magento.com/guides/v2.0/architecture/archi_perspectives/domain_layer.html

Und ein Kommentar zu einer verwandten Frage lautete:

das Repository verwenden werden Sie ein Produktdatenmodell ( Api/Data/Product), die ein Produktmodell ist in eine abgespeckte DTO umgewandelt. Etwas zu beachten, da sie ganz anders sind

Aber soweit ich sehe, sind die Objekte unter normalen Bedingungen die gleichen, nur die Rückgabetypen pro phpDoc unterscheiden sich ( Magento\Catalog\Api\Data\ProductInterface/ Magento\Catalog\Model\Product)

Fabian Schmengler
quelle

Antworten:

23

Der Grund, ProductRepository's get/ getByIdanstelle eines ProductFatory's zu verwendenload() Methode von liegt darin, dass die erstere eine höhere Ebene aufweist als die letztere.

A gibt ProductRepository- genau wie A ProductFactory- möglicherweise ein Product Modell zurück , aber M2 möchte nicht, dass Sie dies berücksichtigen. Das ist nicht , was \Magento\Catalog\Api\ProductRepositoryInterface::getById()‚s doc Block sagt. Es heißt @return \Magento\Catalog\Api\Data\ProductInterface, welches Interface ein Produktmodell ist implementiert.

SO, sollten Sie die API-Ebene verwenden, wann immer dies möglich ist, weil:

  • Api/Data Die Ebene wird auch in der Web-API verwendet
  • Modelle können - und werden wahrscheinlich - irgendwann überarbeitet; Api/Data/Productwird nicht.
  • Um ein Produkt in Ihren Klassen zu bekommen, müssen Sie entweder eine konkrete Fabrik ( ProductFactory) oder eine Schnittstelle ( ProductRepository) einspritzen . Ich glaube nicht, dass Sie möchten, dass sich Ihr Modul auf etwas anderes als eine Schnittstelle stützt. Daher bin ich mit dieser Art der Injektion nicht einverstanden .

Ich betrachte es als eine weitere winzige Abstraktionsebene über den Modellen, die die Web-API (REST, SOAP usw.) berücksichtigt .

Zitiere diese Antwort:

Hoffentlich werden Sie Serviceverträge lieben, wenn Ihr benutzerdefiniertes Modul nach den nächsten Versionen von Magento 2 nicht mehr beschädigt wird (natürlich, wenn Sie Serviceverträge nicht umgehen und Modelle / Sammlungen / Ressourcenmodelle direkt verwenden). Und wenn Sie anfangen, die Magento 2-Web-API zu nutzen / verfügbar zu machen, die jetzt auf denselben Serviceverträgen basiert. Sie müssen also nur an einer Stelle Änderungen vornehmen (zB per Plugin) und diese werden überall angewendet. Dies war in Magento 1 unmöglich.

vergiss es
quelle
Nicht genau das, wonach ich gefragt habe, aber das habe ich auch gedacht, danke für die Bestätigung!
Fabian Schmengler
1
But I could also use the old way instead, calling the domain layer directly: (use factory). Is there any case where this would be necessary or useful?. Ja, wenn Sie die Methode eines Modells aufrufen müssen und nicht die eines ModellsApi/Data/Product . Ist das besser? :)
nevvermind
Ja, das macht Sinn :)
Fabian Schmengler
14

Für mich gibt es keinen Grund, die loadMethode über die getById/ zu verwendenget -Methode zu verwenden.

Ich sage nicht, dass ich recht habe, aber so sehe ich die Dinge.

Ok, hier ist die getByIdMethode (die getMethode ist ähnlich, verwendet aber die SKU anstelle der ID):

public function getById($productId, $editMode = false, $storeId = null, $forceReload = false)
{
    $cacheKey = $this->getCacheKey(func_get_args());
    if (!isset($this->instancesById[$productId][$cacheKey]) || $forceReload) {
        $product = $this->productFactory->create();
        if ($editMode) {
            $product->setData('_edit_mode', true);
        }
        if ($storeId !== null) {
            $product->setData('store_id', $storeId);
        }
        $product->load($productId);
        if (!$product->getId()) {
            throw new NoSuchEntityException(__('Requested product doesn\'t exist'));
        }
        $this->instancesById[$productId][$cacheKey] = $product;
        $this->instances[$product->getSku()][$cacheKey] = $product;
    }
    return $this->instancesById[$productId][$cacheKey];
}

Wie Sie sehen können, haben Sie folgenden Code eingefügt:

$productFactory->create()->load($id);

Ist Teil dieser Funktion.

Die zusätzliche Bedingung verwendet jedoch zwischengespeicherte Instanzen, um ein zusätzliches Neuladen zu vermeiden, falls Sie zuvor die getByIdoder die getMethode für dieselbe ID verwendet haben (oder sku bei der getMethode) .

Möglicherweise besteht ein guter Grund für die Verwendung loaddarin, die Verwendung dieser zwischengespeicherten Instanzen zu vermeiden (in diesem Fall kann dies ein guter Grund sein, den ich nicht kenne), aber getByIddie getMethoden und haben einen $forceReloadParameter, der auf true gesetzt werden kann Vermeiden Sie die Verwendung dieser Cache-Instanzen.

Deshalb gibt es für mich keinen guten Grund, loadmethod over getByIdoder getmethods zu verwenden.

Raphael bei Digital Pianism
quelle
2

Bitte verstehen Sie den Unterschied zwischen Repositorys und Sammlungen.

Wenn Sie in Ihrem Beispiel Repositorys verwenden, erhalten Sie ein Array Magento\Catalog\Api\Data\ProductInterface, das sich vom Abrufen einer Auflistung von unterscheidet Magento\Catalog\Model\Product.

Repositorys und Datenschnittstellen bieten Ihnen ein hohes Schnittstellenlevel, das in zukünftigen Releases als kompatibel garantiert werden sollte . Deshalb ist es der vorgeschlagene Ansatz.

Ich hoffe es hilft.

Phoenix128_RiccardoT
quelle