Wann sollten wir ein Repository und eine Factory in Magento 2 verwenden?

75

Ich habe in Magento 2 einige Tutorials durchgearbeitet, was mich ein wenig verwirrt. Ich sehe, dass es grundsätzlich zwei Möglichkeiten gibt, wie wir Geschäftseinheiten lesen / schreiben können:

Daten abrufen

Verwenden eines Factory-Ansatzes

$object = $this->myFactory->create();
$object->load($myId);

Verwenden eines Repository-Ansatzes

$repo   = $this->myRepository();
$object = $repo->getById($myId);

Daten speichern

Verwenden eines Factory-Ansatzes

$object = $this->myFactory->create();
$object->load($myId);
$object->setData('something', 'somethingDifferent')->save();

Verwenden eines Repository-Ansatzes

$repo   = $this->myRepository();
$object = $repo->getById($myId);
$object->setData('something', 'somethingDifferent');
$repo->save($object);

Ich kann auch sehen, dass sowohl ein Repository als auch eine Factory-Klasse mithilfe der Abhängigkeitsinjektion injiziert werden können. Das ist zumindest für mich verwirrend.

Wann sollten wir einen Repository-Ansatz und einen Factory-Ansatz verwenden? Was ist die beste Vorgehensweise, die wir befolgen müssen?

Rajeev K Tomy
quelle
Ein gutes Beispiel für die Verwendung von Factory, CollectionFactory und Repository finden Sie unter \ Magento \ Setup \ Fixtures \ CategoryResolver
Ricardo Martins,

Antworten:

72

Wenn es ein Repository gibt und es das tut, was Sie gut brauchen, ziehen Sie immer das Repository vor.

Repositorys sind Teil der Serviceverträge (sie sind Implementierungen von Schnittstellen in Api), dh sie sind als öffentliche Schnittstelle zu anderen Modulen gedacht.

Verwenden Sie Repositorys zum vollständigen Laden

$model->load()ist nicht Bestandteil des Servicevertrages. Ich hatte eine Frage zu diesem bestimmten Thema. Vielleicht finden Sie die Antworten hilfreich: Gibt es jemals einen Grund, $ model-> load () Serviceverträgen vorzuziehen?

Verwenden Sie Factories, um neue Entitäten zu erstellen

In Repositorys gibt es keine Methoden zum Erstellen einer neuen Entität. In diesem Fall benötigen Sie eine Factory. Verwenden Sie jedoch die Factory als Schnittstelle , z. B. Magento\Catalog\Api\Data\ProductInterfaceFactory- Sie erstellt die richtige Implementierung basierend auf der DI-Konfiguration.

Verwenden Sie dann die repository->save()Methode, um es zu speichern.

Verwenden Sie Collection Factories, wenn Sie mehr Kontrolle benötigen

Das Folgende ist keine offizielle bewährte Methode von Magento, aber derzeit können Sie in Repositorys nicht genau steuern, was geladen werden soll. Mit der Suchkriterien-API können Sie Filter definieren. Es gibt jedoch beispielsweise keine Möglichkeit, bestimmte EAV-Attribute auszuwählen oder anzugeben, welche Indextabellen verknüpft werden sollen.

Hierbei handelt es sich um Implementierungsdetails, die in den Servicevertrags-APIs ausgeblendet sind. Oft sind diese Implementierungsdetails jedoch von Bedeutung und Sie erhalten eine schlechte Leistung, wenn Sie sie ignorieren. Aus diesem Grund zögere ich nicht mehr, die zugrunde liegenden Sammlungen zu verwenden, sobald die Repositorys mich einschränken.

Fabian Schmengler
quelle
2
Könnten Sie ein Codebeispiel für die Verwendung von Factories zum Erstellen neuer Entitäten geben , bei der Erläuterung fehlen einige Details und sie ist schwer zu verstehen. Vielen Dank.
Key Shang
1
@Key hilft das? devdocs.magento.com/guides/v2.2/extension-dev-guide/…
Fabian Schmengler
Vielen Dank. Aber das use the factory for the interface, such as Magento\Catalog\Api\Data\ProductInterfaceFactory - it will create the right implementation based on DI configuration.ist der Punkt, den ich nicht verstehen kann. Die Entwickler-Anleitungen führen nicht in die InterfaceFactory ein . Wie kann man eine repository->save()Methode verwenden, um neue Entitäten zu speichern? Ich kann nur Factory verwenden, um neue Entitäten zu speichern, nicht Repository.
Key Shang
@Key Shang, dies bedeutet, dass die Schnittstelle Ihnen alle festgelegten Datenfunktionen zum Speichern jeder einzelnen Tabellenspalte bietet. Versuchen Sie daher, die Schnittstelle zu verwenden, wo immer dies möglich ist, um neue Datensätze zu speichern. InterfaceFactory-Klassen werden im Rahmen von di: compile erstellt, sodass Sie sie im Ordner var / generation sehen können.
Stevensagaar
@stevensagaar Danke, ich kann es jetzt verstehen.
Key Shang
21

Gute Frage.

Selbst wenn sowohl Repositories als auch Factories uns den Zugriff auf eine Entität ermöglichen, sollten wir uns auf deren Verantwortung konzentrieren .

Aus der Magento-Dokumentation : "Fabriken sind Serviceklassen, die nicht injizierbare Klassen instanziieren, dh Modelle, die eine Datenbankentität darstellen. Sie bilden eine Abstraktionsebene zwischen dem ObjectManager und dem Geschäftscode."

Aus dem Artikel von Alan Storm : "Ein Repository-Objekt ist für das Lesen und Schreiben Ihrer Objektinformationen in einen Objektspeicher verantwortlich."

Meine Interpretation lautet: Wenn unser Ziel darin besteht, mit nicht injizierbaren (sogenannten "neubaren") Objekten zu arbeiten, sollten wir Fabriken verwenden; Wenn unser Fokus auf dem Suchen / Lesen / Schreiben von Objekten in einem Objektspeicher liegt, sollten wir Repositories verwenden.

Dies ist meine idealistische Herangehensweise an das Thema; Denken Sie daran, dass die tatsächliche Implementierung uns dazu zwingen kann, Dinge durcheinander zu bringen, wie von Alan hervorgehoben.

Genießen.

Alessandro Ronchi
quelle
5

Ich würde sagen, der Weg in die Zukunft besteht darin, Repositorys zu verwenden, da sie eine Codetrennung zwischen Lesen / Schreiben von Daten und Geschäftslogik ermöglichen.

Es gibt einen sehr detaillierten Artikel von Alan Storm, der erklärt, wie man Repositories benutzt, aber auch einige Nachteile dieser neuen Methode untersucht: http://alanstorm.com/magento_2_understanding_object_repositories/

Erklären Sie anhand der Magento-Dokumentation die Vorteile dieses neuen Ansatzes: http://devdocs.magento.com/guides/v2.0/extension-dev-guide/service-contracts/service-contracts.html

Marina Vilcea
quelle
2
Danke für die Antwort. Ich bekomme diesen Zweifel tatsächlich durch den Artikel von alanstorm auf den Kopf. :)
Rajeev K Tomy
3
In der Tat lässt es Sie nachdenken, aber das ist wahrscheinlich eine gute Sache. Auch wenn dies die von Magento vorgeschlagene Best Practice ist, bedeutet dies nicht, dass Entwickler keine Fragen stellen und einige Aspekte kritisieren können. Es gibt auch noch Situationen, die von den Repositorys nicht abgedeckt werden. Im Zusammenhang mit der Erstellung von Erweiterungen, die in zukünftigen Releases mithilfe von Repositorys nicht mehr funktionieren, sollte jedoch berücksichtigt werden. Ich bin mir außerdem sicher, dass sie sich weiterentwickeln und mehr darüber berichten werden, was Entwickler brauchen.
Marina Vilcea
Ich stimme Ihrem Kommentar zu 100% zu. Das hoffe ich wirklich. Siehe auch Fabians Antwort.
Rajeev K Tomy
Ja, ich habe gesehen :) hat seine Antwort bereits positiv bewertet. Danke für die tolle Frage!
Marina Vilcea
Außerdem habe ich irgendwo gelesen, dass die Verwendung einer Datenmanipulationsmethode auf niedrigerer Ebene für die Installation / Aktualisierung von Skripten $setup->updateTableRow(...);oder Fabriken in Ordnung ist. Ich bin mir nicht sicher, aber es scheint, als würden die Argumente für die Verwendung einer höheren Ebene auch für diesen Bereich gelten. Was denken Sie?
Medmek
1

Hoffe, diese Antwort könnte auch anderen Erweiterungsentwicklern helfen.

Wir müssen das Modell nur mit dem Repository speichern.

  1. Das Factory-Modell in Magento 2 enthält nur sehr wenige Daten.
  2. Andererseits enthält das Repository-Modell alle Daten im Fall von EAV-Attributen, die sich auf Kunden, Produkte usw. beziehen.
  3. Verwenden Sie zum Speichern des Modells immer Repository, um eine Entität zu speichern. Wenn das Factory-Modell zum Speichern des Modells verwendet wird, werden alle Nicht-System-EAV-Attribute gelöscht, die sich auf diese Entität beziehen (Kunde, Produkt usw.).

  4. Zum Laden des Modells ist das Repository die beste Option, um das Modell mit der Methode getById () abzurufen.

Ich werde empfehlen, Repository so oft wie möglich zu verwenden, insbesondere zum Speichern von Modellen.

Sachin
quelle
1

Jetzt sind Methoden (Modelle) zum Laden, Speichern und Löschen veraltet. Wir können also ein Ressourcenmodell oder ein Repository verwenden.

Magento verwendet jetzt das Entity Manager-Konzept zum Speichern, Löschen und Laden von Vorgängen.

Ressourcenmodelle verfügen über ein Objekt des Entitätsmanagers, um diese Vorgänge auszuführen.

$categoryModel = $this->_objectManager->create('\Magento\Catalog\Model\CategoryFactory')->create();        
  $categoryResource = $this->_objectManager->create('\Magento\Catalog\Model\ResourceModel\Category');        
  $categoryResource->load($categoryModel, 3);        
  echo $categoryModel->getName();
Siva Kumar Koduru
quelle