Warum definieren einige Klassen Injektionen sowohl in ihrem Konstruktor als auch in di.xml?


12

Ich verstehe nicht, warum in einigen Klassen ihre Abhängigkeitsinjektionen zweimal deklariert werden - einmal im di.xmlund im Konstruktor der konkreten Klasse.

Zum Beispiel in Magento\Backend\Model\Url, der di.xmlhat diesen Satz von Typen für DI definiert:

<type name="Magento\Backend\Model\Url">
    <arguments>
        <argument name="scopeResolver" xsi:type="object">
Magento\Backend\Model\Url\ScopeResolver</argument>
        <argument name="authSession" xsi:type="object">
Magento\Backend\Model\Auth\Session\Proxy</argument>
        <argument name="formKey" xsi:type="object">
Magento\Framework\Data\Form\FormKey\Proxy</argument>
        <argument name="scopeType" xsi:type="const">
Magento\Store\Model\ScopeInterface::SCOPE_STORE </argument>
        <argument name="backendHelper" xsi:type="object">
Magento\Backend\Helper\Data\Proxy</argument>
    </arguments>
</type>

Gleichzeitig werden in der konkreten Klasse die in di.xml definierten Klassen, die für die Injektion erforderlich sind, im Konstruktor erneut deklariert:

<?php
    public function __construct(
        \Magento\Framework\App\Route\ConfigInterface $routeConfig,
        \Magento\Framework\App\RequestInterface $request,
        \Magento\Framework\Url\SecurityInfoInterface $urlSecurityInfo,
        \Magento\Framework\Url\ScopeResolverInterface $scopeResolver,
        \Magento\Framework\Session\Generic $session,
        \Magento\Framework\Session\SidResolverInterface $sidResolver,
        \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory,
        \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        $scopeType,
        \Magento\Backend\Helper\Data $backendHelper,
        \Magento\Backend\Model\Menu\Config $menuConfig,
        \Magento\Framework\App\CacheInterface $cache,
        \Magento\Backend\Model\Auth\Session $authSession,
        \Magento\Framework\Encryption\EncryptorInterface $encryptor,
        \Magento\Store\Model\StoreFactory $storeFactory,
        \Magento\Framework\Data\Form\FormKey $formKey,
        array $data = []
) {
    //...
}
?>

Wenn wir uns den Konstruktor oben ansehen, \Magento\Framework\App\Route\ConfigInterface $routeConfigist er beispielsweise nicht in definiert di.xml. Es ist nur im Konstruktor definiert und Magento wird das weiterhin routeConfigzur Verwendung in die Klasse einfügen, nicht wahr? Gleiches gilt für \Magento\Framework\Encryption\EncryptorInterface $encryptorund einige andere.

Warum müssen dann die anderen Injektionen in beiden di.xmlund im Konstruktor definiert werden, wenn diese Deklarationen im Konstruktor ausreichen, damit Magento diese Abhängigkeiten zur Verwendung in die Klasse einfügt?

Antworten:


15

Wie in der Dokumentation angegeben , kann in Magento 2 di.xmlFolgendes verwendet werden:

Sie können die Klassenkonstruktorargumente in Ihrem di.xmlim Argumentknoten konfigurieren . Der Objektmanager fügt diese Argumente während der Erstellung in die Klasse ein. Der Name des in der XML-Datei konfigurierten Arguments muss dem Namen des Parameters im Konstruktor in der konfigurierten Klasse entsprechen.

In Ihrem Fall ist es etwas komplex. Ich werde jedes Argument einzeln erklären:

  • \Magento\Framework\App\Route\ConfigInterface $routeConfig: Dies ist eine Schnittstelle, daher kann sie nicht direkt verwendet werden . Die Präferenz für diese Klasse ist in definiertapp/etc/di.xml und es ist die Magento\Framework\App\Route\ConfigKlasse
  • \Magento\Framework\App\RequestInterface $request : Gleiches gilt für diese Klasse, die Präferenz ist Magento\Framework\App\Request\Http
  • \Magento\Framework\Url\SecurityInfoInterface $urlSecurityInfo: gleich hier wieder mit Magento\Framework\Url\SecurityInfo\Proxyals Präferenz
  • \Magento\Framework\Url\ScopeResolverInterface $scopeResolver: hier fangen wir mit dem interessanten Stück an. In app/etc/di.xmleiner Präferenz ist für diese Schnittstelle definiert und es ist die Magento\Framework\Url\ScopeResolverKlasse. Für das Magento\Backend\Model\UrlMagento 2 muss jedoch eine andere Klasse verwendet werden, und somit wird definiert, welche Klasse in der von di.xmlIhnen geposteten Klasse Magento\Backend\Model\Url\ScopeResolververwendet wird.
  • \Magento\Framework\Session\Generic $session Dies ist eine normale Klasse und kann daher so verwendet werden.
  • \Magento\Framework\Session\SidResolverInterface $sidResolver: zurück zu einer Schnittstelle, die Präferenz ist noch in definiert app/etc/di.xmlund es istMagento\Framework\Session\SidResolver\Proxy
  • \Magento\Framework\Url\RouteParamsResolverFactory $routeParamsResolverFactory : Dies ist eine Factory-Klasse, daher kann sie so verwendet werden.
  • \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver: zurück zu unserer app/etc/di.xmlund die Präferenz istMagento\Framework\Url\QueryParamsResolver
  • \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig: ein anderer Fall hier, in dem ** eine Präferenz definiert ist app/etc/di.xmlund es ist Magento\Framework\App\Config.
  • $scopeType: hier haben wir nur eine Variable ohne Klasse davor. Ihr Modul di.xmlgibt an, dass Magento\Store\Model\ScopeInterface::SCOPE_STOREdies als Wert dieser Variablen verwendet werden soll. **
  • \Magento\Backend\Helper\Data $backendHelper: hier hätten wir diese Klasse so verwenden können. Hier wird jedoch ein Proxy verwendet, da diese Klasse nicht unbedingt verwendet wird (Einzelheiten zu Proxy-Klassen finden Sie in diesem Beitrag: Magento 2: Praktische Erklärung, was eine Proxy-Klasse ist? )
  • \Magento\Backend\Model\Menu\Config $menuConfig : Wir können diese Klasse so verwenden, wie sie ist.
  • \Magento\Framework\App\CacheInterface $cache: eine andere Präferenz, die in app/etc/di.xmlfür diese Schnittstelle definiert ist, nämlichMagento\Framework\App\Cache\Proxy
  • \Magento\Backend\Model\Auth\Session $authSession: Auch hier hätten wir die Klasse so verwenden können, aber wir verwenden stattdessen eine Proxy-Klasse für das verzögerte Laden.
  • \Magento\Framework\Encryption\EncryptorInterface $encryptor: Springe app/etc/di.xmlwieder zum und wir finden Magento\Framework\Encryption\Encryptorals Präferenz
  • \Magento\Store\Model\StoreFactory $storeFactory : eine Fabrik, damit wir sie so nutzen können.
  • \Magento\Framework\Data\Form\FormKey $formKey: hier verwenden wir wieder die Magento\Framework\Data\Form\FormKey\ProxyProxy-Klasse zum verzögerten Laden.
  • array $data = []: Dieser kommt immer als letzter und wird automatisch auf ein leeres Array gesetzt. Weitere Informationen finden Sie hier: Magento 2: Was ist der Konstruktorparameter $ data array?

Zusammenfassen

Global gesehen sind Klassenkonstruktorparameter Schnittstellen oder nicht instanziierbare Klassen. Auf diese Weise di.xmlkönnen Sie die Abhängigkeiten anpassen, die Sie für jeden Klassenkonstruktor verwenden möchten. Es gilt auch für instanziierbare Klassen. Zum Beispiel ein Klassenkonstruktor, der eine Produktklasse als Konstruktorargument verwendet. Es kann im konfigurierbaren Produktmodul angepasst werden, sodass stattdessen eine konfigurierbare Produktklasse als Argument verwendet wird.


Ist für einen Schnittstellenparameter immer eine Präferenz erforderlich? Kann es als Fallback gesehen werden? Ist es sinnvoll, nur ein konkretes Argument in der Konfiguration zu definieren, ohne irgendwo eine Präferenz zu haben? Oder ist das nicht möglich?
Robsch

6

Es ist wichtig, den Unterschied zwischen der Definition von Abhängigkeiten und der Konfiguration von Abhängigkeiten zu verstehen .

Abhängigkeiten sind in di.xml nicht definiert. Abhängigkeiten werden innerhalb des Konstruktors der jeweiligen Klasse definiert, indem eine Schnittstelle, eine Zusammenfassung oder eine Factory als Typ dieser spezifischen Abhängigkeit angegeben wird, z. B. $routeConfigeine Abhängigkeit vom Typ \Magento\Framework\App\Route\ConfigInterface.

Auf der anderen Seite können Sie di.xmldie Abhängigkeiten mithilfe von <preference/>Knoten und / oder xpath:type/arguments/argumentKnoten konfigurieren (manchmal gekoppelt mit erweiterten Konfigurationsknoten wie <virtualType/>oder <proxy/>). Das Konfigurieren einer Abhängigkeit bedeutet einfach, das Konstruktorargument eines Objekts einer Implementierung / einem Objekt / einem Beton zuzuordnen .

Sie möchten, dass Abhängigkeiten über di.xml konfiguriert werden können, damit Sie sie austauschen und unter bestimmten Bedingungen eine andere Implementierung für eine bestimmte Schnittstelle oder ein bestimmtes Argument verwenden können (lesen Sie das Beispiel weiter, um zu verstehen, was bestimmte Bedingungen bedeuten sollen).

Wenn Sie beispielsweise Ihre Erweiterung entwickeln, erstellen Sie zuerst eine neue Klasse (wir nennen diese neue Klasse eine Implementierung ). Ihre neue Klasse implementiert die \Magento\Framework\App\Route\ConfigInterfaceSchnittstelle und verfügt in ihrem Körper über eine konkrete Funktionalität, die den Schnittstellenvertrag einhält. Jetzt beginnt der Konfigurationsteil : Um Magento anzuweisen, Ihre neu definierte Implementierung zu verwenden, müssen Sie diese Implementierung als Abhängigkeit für das Objekt konfigurierenMagento\Backend\Model\Url . Sie führen diese Konfiguration in den di.xmlDateien oder in Ihrem Modul durch. In diesem Fall müssen Sie den <preference/>Knoten verwenden, um die Schnittstelle Ihrer neuen Implementierung zuzuordnen. In anderen Fällen würden Sie den detaillierteren xpath:type/arguments/argument di.xmlKnoten verwendenOrdnen Sie nur bestimmte Argumente (auch bekannt als Abhängigkeiten, auch bekannt als Schnittstellen) eines Betons bestimmten Implementierungen zu . Nun wird Ihre Implementierung nur dann aktiv sein , als eine Abhängigkeit für das Objekt \Magento\Backend\Model\Url unter bestimmten Bedingungen , beispielsweise in dem Codeausführungsablauf der aktuellen Anwendungsanforderung ein Objekt vom Typ Magento\Backend\Model\Urlerstellt wird , und es muss eine Implementierung für den Konstruktor definierte Abhängigkeit genannt , $routeConfigdie ist vom Typ \Magento\Framework\App\Route\ConfigInterface.

Es ist so ziemlich so, als würde man sagen:

"Hey Mr. ObjectManager! Wenn eine Objektinstanz vom Typ Magento\Backend\Model\Urlangefordert wird, schauen Sie sich bitte zuerst die Definition des Klassenkonstruktors an und analysieren Sie die definierten Abhängigkeiten darin . Ich möchte, dass Sie dann in der endgültigen, zusammengeführten, di.xmlaktuellen HTTP-Anforderung die Konfiguration für jede konfigurierte Abhängigkeit , die im Klassenkonstruktor Magento \ Backend \ Model \ Url definiert ist . Sie geben mir diese konfigurierte Abhängigkeitsimplementierung. "

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.