Ok, also gestern hatten wir ein großes Gespräch mit anderen Leuten aus der Magento-Community über die direkte Verwendung der ObjectManager
in Klassen / Vorlagen .
Ich kenne bereits die Gründe, warum wir den ObjectManager nicht direkt verwenden sollten, unter Berufung auf Alan Kent :
Es gibt verschiedene Gründe. Der Code funktioniert, es wird jedoch empfohlen, die ObjectManager-Klasse nicht direkt zu referenzieren.
- Weil wir es so sagen! ;-) (besser ausgedrückt als konsistenter Code ist guter Code)
- Der Code könnte in Zukunft mit einem anderen Abhängigkeitsinjektionsframework verwendet werden
- Das Testen ist einfacher - Sie übergeben Scheinargumente für die erforderliche Klasse, ohne einen Schein-ObjectManager bereitstellen zu müssen
- Abhängigkeiten bleiben klarer - es ist offensichtlich, wovon der Code über die Konstruktorliste abhängt, anstatt Abhängigkeiten in der Mitte des Codes zu verbergen
- Es ermutigt Programmierer, Konzepte wie Kapselung und Modularisierung besser zu überdenken - wenn der Konstruktor groß wird, ist es vielleicht ein Zeichen, dass der Code überarbeitet werden muss
Nach dem, was ich in StackExchange gesehen habe, entscheiden sich viele Leute für die einfache / kurze / nicht empfohlene Lösung, zum Beispiel für Folgendes:
<?php
//Get Object Manager Instance
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
//Load product by product id
$product = $objectManager->create('Magento\Catalog\Model\Product')->load($id);
Anstatt den schmerzhaften, aber empfohlenen Prozess zu durchlaufen :
- Erstellen eines Moduls
- Präferenzen angeben
- Abhängigkeiten einschleusen
- Deklarieren Sie eine öffentliche Methode
Und hier kommt das Dilemma, dass Magento 2-Kerndateien den ObjectManager oft direkt aufrufen . Ein kurzes Beispiel finden Sie hier: https://github.com/magento/magento2/blob/develop/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Form.php#L57
Also hier sind meine Fragen:
- Warum macht Magento das, wovon sie uns raten? Heißt das, es gibt einige Fälle, in denen wir die
ObjectManager
direkt verwenden sollten ? Wenn ja, wie lauten diese Fälle? - Welche Konsequenzen hat die direkte Verwendung des ObjectManagers ?
quelle
The intent of zend-servicemanager is for use as an Inversion of Control container. It was never intended as a general purpose service locator [...]
. Das gilt auch für M2. Überprüfen Sie auch denThere are valid use cases
Abschnitt, der auch hier gilt.Antworten:
Sie sollten den ObjectManager nicht direkt verwenden!
Ausnahme von der Regel sind:
__wakeup
,serialize
usw.quelle
Brutale Antwort: M2 ist ein Port von M1 - kein vollständiges Umschreiben. Gehen Sie also nicht davon aus, dass der gesamte M2-Code (leider) noch perfekt portiert ist. Nur weil Sie etwas in der M2-Codebasis finden, heißt das nicht, dass dies die beste Methode ist. Manchmal ist es nur "wir haben es noch nicht geschafft, es zu reparieren".
Weniger brutal: Wie in anderen Antworten heißt es manchmal, dass Sie es verwenden MÜSSEN, da es keine Alternative gibt. In anderen Fällen kann dies aus Gründen der Abwärtskompatibilität auftreten. Und manchmal ist es sinnvoll, Framework-Code direkt zu verwenden, da es sich um Framework-Code handelt. Aber wenn ich raten müsste, ohne auf Code zu achten, sollten viele wirklich repariert werden, aber die Priorität war noch nicht hoch genug, um dies zu tun.
Denken Sie nur an den guten Rat der Eltern: "Kinder, tun Sie, was ich sage, nicht was ich tue!"
quelle
Sie sollten niemals verwenden
\Magento\Framework\App\ObjectManager::getInstance()
.Es besiegt den Zweck der Abhängigkeitsinjektion. Wir sind zurück bei
Mage::getModel()
.Der Objektmanager sollte nur in Fabriken und dann wie in einem Konstruktor injiziert verwendet werden.
Der Vorteil dieser Methode ist, dass weniger Code geschrieben werden muss. Aber das macht es nicht OK.
Die Tatsache, dass dies immer noch im Kern verwendet wird, liegt daran, dass es noch nicht überarbeitet wurde. Ich hoffe es wird.
quelle
di.xml
erstellen mit eine key => class name map und fügen diese Map in den Konstruktor der Factory ein und verwenden die Factory, um die Klasse über objectmanager zu instanziierenOhne die ganze Geschichte hier zu kennen, ist meine Vermutung:
Bei der Entwicklung von M2 das Magento Team irgendwann lief ein automatisiertes Skript , das Vorkommen ersetzt
Mage:getModel()
,Mage::getSingleton()
,$layout->createBlock()
etc. , um die Objektmanager zu verwenden.Späteres Refactoring sollte dies behoben haben, um stattdessen die ordnungsgemäße Abhängigkeitsinjektion zu verwenden, aber es gab nicht genügend Zeit / Ressourcen, um alle Vorkommen zu konvertieren.
Auch das Magento-Team scheint dies in letzter Zeit als Fluchtmechanismus zu nutzen. Anstatt eine vorhandene Implementierung zu beschädigen (indem der Konstruktor geändert werden muss), wird die neue Abhängigkeit einfach über den ObjectManager ausgeblendet. Ich kann nicht sagen, dass ich diesem Ansatz zustimme - schlechteren Code zu schreiben, um einen BC-Bruch zu vermeiden.
Ich denke, Ihre Frage enthält bereits genügend Gründe. Im Allgemeinen wird eine versteckte Abhängigkeit erstellt, dh die Abhängigkeit befindet sich in den Implementierungsdetails und ist nicht nur für den Konstruktor sichtbar.
quelle
Sollte Object Manager nicht direkt verwenden!
Zum Beispiel:
Auch wenn Sie mit Ereignisbeobachtern oder Plugins arbeiten, sollten Sie diese niemals direkt verwenden.
Sie könnten es in Fabriken verwenden, aber außer dass Sie den Objekt-Manager zuerst in den Konstruktor einfügen sollten, dann können Sie sein Objekt in Ihrer Methode verwenden
Bevorzugt zu verwenden:
1) privates Objekt deklarieren:
2) füge den Konstruktor ein und initialisiere:
3) Verwenden Sie in irgendeiner Methode:
quelle
::getInstance()
Der Hauptgrund, warum Entwickler davon dringend abgeraten werden, den Objekt-Manager direkt zu verwenden, besteht darin, dass die Erweiterung bei direkter Verwendung des Objekt-Managers im kompilierten Release-Modus nicht installiert werden kann.
Im Release-Modus wird dies für Ihre Kunden unterbrochen, einschließlich aller Kunden in der Magento Cloud.
Ein relativ großer Teil der Entwickler (ca. 75%) testet ihre Erweiterungen nicht, um festzustellen, ob sie im Release-Modus installiert werden können. Treffen Sie daher nicht auf die Probleme, die durch die falsche Verwendung von ObjectManager entstehen.
Ab 2017 führt der Magento Marketplace einen Kompilierungs- und Installationstest für alle über ihn verkauften Erweiterungen durch. Wenn Ihre Erweiterung den Objekt-Manager direkt verwendet, werden diese Tests nicht bestanden und vom Marktplatz zurückgewiesen, bis Sie das Problem beheben und erneut hochladen.
quelle
Sie können versuchen, ein Objekt von objectManager zu erstellen, und sollten objectManager nicht direkt verwenden .
Verwenden Sie so etwas wie,
quelle