In den Regeln für die Verwendung der Abhängigkeitsinjektion geben die Magento 2-Devdocs Folgendes an:
Newable-Objekte sollten weder einen Feldverweis auf ein injizierbares Objekt enthalten noch einen in ihrem Konstruktor anfordern. Dies ist ein Verstoß gegen das Gesetz von Demeter .
Ich verstehe, dass dies ein gutes Ziel ist, aber wie ist dies mit Magento 2-Modellen tatsächlich möglich?
Wenn wir einen Blick auf das Kundenmodul haben, die als leuchtendes Beispiel für die neue Architektur vorgestellt wurde, werden die Kunden Modell sieht Konstruktor Signatur wie folgt aus :
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Eav\Model\Config $config,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Customer\Model\ResourceModel\Customer $resource,
\Magento\Customer\Model\Config\Share $configShare,
\Magento\Customer\Model\AddressFactory $addressFactory,
\Magento\Customer\Model\ResourceModel\Address\CollectionFactory $addressesFactory,
\Magento\Framework\Mail\Template\TransportBuilder $transportBuilder,
GroupRepositoryInterface $groupRepository,
\Magento\Framework\Encryption\EncryptorInterface $encryptor,
\Magento\Framework\Stdlib\DateTime $dateTime,
CustomerInterfaceFactory $customerDataFactory,
DataObjectProcessor $dataObjectProcessor,
\Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
\Magento\Customer\Api\CustomerMetadataInterface $metadataService,
\Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = []
)
Und Magento\Framework\Model\Context
allein, was von allen Modellen verwendet wird, benötigt fünf injizierbare Argumente.
Anscheinend sind Modelle, obwohl neuwertig , überhaupt kein gutes Beispiel für diese Regel.
Ich möchte Best Practices mit meinen eigenen Klassen (nicht einmal Modellen) befolgen, benötige jedoch Zugriff auf Dinge wie Repositorys verwandter Entitäten oder auf den Event-Manager. Was wäre der bevorzugte Weg, um damit umzugehen, ohne die Regel von oben zu brechen?
Ich neige derzeit dazu, es zu ignorieren oder es bestenfalls als freundliche Richtlinie zu betrachten, nicht in der Regel.
quelle
Wir versuchen, die Benutzer davon abzuhalten, direkt auf den Code in einem Modul zuzugreifen, und stattdessen eine kontrollierte, genau definierte API zu verwenden. Ziel ist es, reibungslosere Updates zwischen den Releases zu ermöglichen. Je mehr Benutzer eine definierte API verwenden, desto reibungsloser werden die Upgrades.
Ein wichtiges Konzept in den Dateien di.xml ist das Element "Einstellungen". Der Code kann auf Schnittstellendefinitionen verweisen (und ist daher nicht an eine bestimmte Implementierung gebunden). Wenn Sie jedoch nach einer Instanz fragen, weiß er, welche Klasse verwendet werden soll.
Wenn Sie also eine CustomerInterface-Instanz möchten (das ist eine Klasse, die die Schnittstelle implementiert), fragen Sie nach einer Instanz der Schnittstelle (Sie suchen nicht nach der Implementierungsklasse). Wir werden nach einem Element für Sie suchen und dieses verwenden, um die Implementierungsklasse zu identifizieren. Auf diese Weise könnte ein anderes Modul die Dateipräferenz di.xml ersetzen und in eine andere Implementierungsklasse wechseln (wenn es einen guten Grund dafür gibt).
Wenn Sie Objekte auf diese Weise über den Objektmanager erstellen, müssen Sie die Argumente für die Konstruktorliste nicht angeben. Der Objektmanager verwendet erneut die Datei di.xml, um alle erforderlichen Datenstrukturen zu finden, und stellt sie automatisch dem Konstruktor zur Verfügung.
Der Unterschied zwischen "Serviceklassen" und "Datenmodellen" in einer separaten Antwort besteht darin, dass "Serviceklassen" (von denen ich annehme, dass sie die Schnittstellen im Api-Verzeichnis bedeuten) Methoden zum Aufrufen bereitstellen. Die "Datenmodelle" (von denen ich annehme, dass sie die Schnittstellen im Api / Data-Verzeichnis bedeuten) sind Datenstrukturen, die an / von "Serviceklassen" übergeben werden. Das Ziel ist, dass jemand außerhalb des Moduls nicht wissen muss, welche Klasse die Schnittstellen implementiert. Es könnte ein Modell sein, es könnte ein Wertobjekt sein, es sollte keine Rolle spielen, solange Sie auf die Schnittstellen programmieren und niemals Klassennamen direkt erwähnen (außer in der Datei di.xml).
quelle