Magento 2 Helper-Instanz

11

Wenn ich glaube, ich habe meinen Kopf um das DI-System von Magento 2 gewickelt, kommt etwas auf und wickelt es ab.
Ich sehe im Kerncode verschiedene Möglichkeiten, auf einen Helfer zuzugreifen.
Zum Beispiel Magento\Catalog\Controller\Category::_initCategorydrin ist dies:

if (!$this->_objectManager->get('Magento\Catalog\Helper\Category')->canShow($category)) {
    return false;
}

Aber in Magento\Catalog\Block\Category\Viewden Helfer wird in den Konstruktor gespritzt

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Catalog\Model\Layer\Category $catalogLayer,
    \Magento\Framework\Registry $registry,
    \Magento\Catalog\Helper\Category $categoryHelper,
    array $data = array()
) {
    $this->_categoryHelper = $categoryHelper;
    $this->_catalogLayer = $catalogLayer;
    $this->_coreRegistry = $registry;
    parent::__construct($context, $data);
}

Dies führte mich zu der Annahme, dass auf die Helfer in Controllern und Blöcken (und Modellen) unterschiedlich zugegriffen werden sollte, aber dann fand ich einen Controller, in den ein Helfer in den Konstruktor injiziert wird Magento\Catalog\Controller\Adminhtml\Product\Action\Attribute.

Bitte klären Sie den Nebel für mich.
Wann sollte ich DI verwenden und wann sollte ich verwenden objectManager? und warum?
Ich habe diese Frage gelesen: Helfer in Magento 2 instanziieren . Dies ist nur eine Folgefrage dazu.

Marius
quelle

Antworten:

10

Ich würde DI nach Möglichkeit bevorzugen, da die Verwendung des Objektmanagers bereits einen Verstoß gegen das Demeter-Gesetz darstellt. Bei Verwendung des Objektmanagers werden diese Abhängigkeiten nur in der Methodenlogik ausgeblendet.

Tobias
quelle
Ja. Genau. Ich werde DI verwenden, aber ich bin gespannt, warum dies im Kern geschieht. Vielleicht konnte jemand die von mir erwähnten Klassen noch nicht umgestalten?
Marius
Afaik, sie bauen immer noch viel um und hoffen, dass sie auch diese Orte berühren. Aber auch nicht über die Prioritäten Bescheid wissen, die existieren müssen, wenn sie tatsächlich irgendwann veröffentlicht werden sollen. Vielleicht werden zuerst einige neue Funktionen oder andere schlechte Praktiken behoben.
Tobias
Was ist, wenn Sie eine Klasse von 10 Funktionen haben und NUR 1 Funktion ein bestimmtes Modell erfordert? Wäre es nicht redundant (aus Sicht der Leistung), das Modell durch Konstruktorinjektion für jede der 10 Funktionen zu laden, während wir es mit dem Objektmanager nur innerhalb einer einzelnen Funktion laden könnten?
JohnyFree
6

Ich weiß nicht so viel über die Magento-Implementierung, aber es sieht so aus, als wäre ObjectManageres ein Service Locator .

Im Allgemeinen ist die Verwendung eines Service Locator für den Zugriff auf Abhängigkeiten in einem Objekt ziemlich schlecht. Lesen Sie diesen Artikel .

Das explizite Definieren Ihrer Abhängigkeiten durch einen Konstruktor ist ein viel besserer Ansatz. Es hilft bei Unit-Tests und Laufzeitproblemen, wenn Services nicht definiert sind.

Wenn Sie den Objektmanager in eine Klasse einfügen, wird Ihrer Klasse im Grunde genommen eine Registrierung hinzugefügt, die Zugriff auf alle Ihre Anwendungsdienste hat, was offensichtlich nicht richtig ist.

Ich benutze ZF2 ein gutes Stück und definiere im Allgemeinen kleine Factory-Klassen für Services, Controller und jede Klasse, die Abhängigkeiten erfordert. Diese Factory-Klassen haben Zugriff auf den Service Locator und greifen auf alle Services zu, von denen das Objekt abhängt, und fügen sie über den Konstruktor ein. Einen Service Locator in einer Fabrik - Klasse ist in Ordnung , da es meist Code wegzuwerfen ist, so etwas wie dies zum Beispiel.

Diese Fabriken sind immer noch leicht zu testen .

IMO, Verwenden Sie nach Möglichkeit eine Konstruktorinjektion. Auch hier weiß ich nicht viel über die Implementierung von Magento und wenn es das Konzept von Fabriken hat, sieht es auf den ersten Blick so aus, als würde es sie unterstützen, aber es ist explizit, Ihre Klassen zu definieren und einen Service Locator zu verwenden, um sie in Factory-Klassen zu erstellen ein viel sauberer Ansatz.

Dies ist von jemandem, der nur begrenzt mit den oben genannten Mustern in Berührung gekommen ist, daher würde ich auch gerne die Gedanken / Erfahrungen anderer zu diesem Thema hören!

Mehr lesen

Aydin Hassan
quelle
Danke für die nette Erklärung. Meine Frage war "Warum gibt es zwei Möglichkeiten, auf einen Helfer im Kern zuzugreifen?" Das ist also ein bisschen unangebracht, aber es hat einige andere Zweifel ausgeräumt, die ich hatte. :) Vielen Dank.
Marius
Ich würde wahrscheinlich sagen, dass es nur etwas ist, das noch nicht überarbeitet wurde. Entweder das oder es könnte eine benutzerfreundliche Sache sein. Die Forderung, dass Verbraucher immer alle ihre Abhängigkeiten in einen Controller einfügen müssen, kann als kontraproduktiv angesehen werden, insbesondere bei der Durchführung von RAD. Wenn den Verbrauchern beide Möglichkeiten für den Zugriff auf Abhängigkeiten eingeräumt werden, kann der RAD-Ansatz verwendet werden, andere können jedoch ihre Abhängigkeiten explizit definieren, wenn sie dies wünschen.
Aydin Hassan
5

Eine andere Möglichkeit, den Helfer (in Vorlagen) zu verwenden, ist:

$this->helper('[Vendor]\[Module]\Helper\[Helper Name]')->getMethodName();

Ich hoffe, es ist nützlich, wenn Sie es noch nicht wussten.

rbncha
quelle
Dies ähnelt in gewisser Weise der Verwendung des Objektmanagers. Ich bin mir nicht sicher, ob es die beste Idee ist.
Marius
1
Die obige Methode gilt meines Wissens nur für Vorlagen. Der Objektmanager wird in Controllern, Blöcken, Modellen usw. verwendet
rbncha
1
Es befindet sich nicht im selben Bereich wie Code, da keine Code-Abhängigkeiten von Vorlagen bestehen. Die Vorlagen sind nur Verbraucher und verschmutzen keine Clients mit fehlerhafter Kapselung.
Demonkoryu
Ich weiß nicht, was Demonkoryu zu sagen versucht. Der beste Weg, den Helfer eines Moduls anzurufen, ist dies. Das ist Magento. Wie sie sagen, soll jeder Block- / Abschnittscode aufrufbar / modifizierbar sein, ohne den Kern zu berühren. Alles hängt also zusammen oder hat Abhängigkeiten.
Rbncha
2

Obwohl es eine alte Frage ist, bin ich mir nicht sicher, ob Marius ihre Antwort bekommen hat. Ich glaube, Marius kann es besser beantworten. Ich möchte es kurz beantworten. Warum schlägt Magento 2 vor, DI anstelle von Helfer zu verwenden?

  • Isolation beim Unit-Test möglich / einfach machen
  • Abhängigkeiten einer Klasse explizit definieren
  • Erleichterung eines guten Designs (z. B. Single-Responsibility-Prinzip (SRP))
  • Die Verwendung von DI in Ihrem Modul verringert das Risiko von Inkompatibilitätsfehlern, wenn Magento die zugrunde liegende Implementierung dieser Schnittstellen ändert. Dies ist ein wichtiges Konzept, das für Erweiterungsentwickler zu verstehen ist.

Warum verwendet der M2-Kern in einigen Fällen möglicherweise kein DI?

  • Abnehmende Anzahl von Klassen
  • Keine unnötigen Schnittstellen erstellen
  • Kein Risiko von Inkompatibilitätsfehlern

Obwohl das Core-Katalogmodul als Helfer verwendet wurde, wurde DI ausgiebig verwendet. Bei meinen Recherchen stellte ich fest, dass Magento 2 nur wenige Funktionen in Core Catalog-Hilfsdateien verwendet, die nicht für Serviceverträge geeignet sind.

Wenn Sie explizit eine von Magento definierte Klasse verwenden müssen (z. B. \ Magento \ Catalog \ Model \ Product), machen Sie die implizite Abhängigkeit explizit, indem Sie von der konkreten Implementierung anstelle der Servicevertragsschnittstelle abhängen.

Zweifellos sollte der Erweiterungsentwickler DI anstelle von Magento1 wie Helper verwenden. Bei der Implementierung gemäß den Richtlinien von Magento 2 ist der Fallout begrenzt. Wenn Sie gegen Empfehlungen verstoßen, treten Probleme auf.

Agilox
quelle
Ja, ich habe in der Zwischenzeit meine Antwort bekommen. Aber danke, dass Sie sich die Zeit genommen haben, um zu antworten. Dies sind wertvolle Informationen für Personen, die online danach suchen.
Marius