DI & Erweitern eines Blocks in Magento 2

15

Ich habe anscheinend Probleme, die Magento 2-Abhängigkeitsinjektion mit Blöcken zu erfassen, und jedes Mal, wenn ich versuche, einen Block zu erweitern, der nicht \ Magento \ Framework \ View \ Element \ Template ist, treten Fehler auf.

Ich möchte einen Block erstellen, der die grundlegende Blockklasse von Magento \ Theme \ Block \ Html \ Header \ Logo erweitert - alles funktioniert einwandfrei, bis ich die Abhängigkeitsinjektion innerhalb der Konstruktmethode versuche:

<?php

namespace Creare\Test\Block\Header;

class Logo extends \Magento\Theme\Block\Html\Header\Logo
{

    protected $_creareHelper;

    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Creare\Seo\Helper\Data $creareHelper,
        array $data = []
    )
    {
        $this->_creareHelper = $creareHelper;
        parent::__construct($context, $data);
    }
}

Sobald ich versuche, meine Helfer-Klasse (oder irgendetwas anderes) zu injizieren, erhalte ich einen Stack-Trace, der mit dem folgenden Fehler beginnt:

Recoverable Error: Argument 2 passed to Magento\Theme\Block\Html\Header\Logo::__construct() must be an instance of Magento\MediaStorage\Helper\File\Storage\Database, array given, called in /Users/adammoss/PhpstormProjects/Magento2/app/code/Creare/Test/Block/Header/Logo.php on line 17 and defined in /Users/adammoss/PhpstormProjects/Magento2/app/code/Magento/Theme/Block/Html/Header/Logo.php on line 33

Wenn ich meinem __construct die gleichen Abhängigkeiten hinzufüge, wie die Datei, die ich von ihr aus erweitere, funktioniert, ist dies sicherlich eine umgekehrte Vorgehensweise, da der Punkt der Klassenvererbung darin besteht, dass ich alle Methoden und Eigenschaften des übergeordneten Elements übernehme.

Ich denke, ich brauche nur eine grundlegende Erklärung von jemandem zum Erweitern von Klassen und Verwenden von DI mit Magento 2. Jede Hilfe sehr geschätzt!

Adam Moss
quelle
"Sicherlich ist das eine rückwärts gerichtete Art, Dinge zu tun", stimmte zu.
James

Antworten:

19

Die Klasse, die Sie erweitern möchten, hat folgenden Konstruktor:

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\MediaStorage\Helper\File\Storage\Database $fileStorageHelper,
    array $data = []
) {
    $this->_fileStorageHelper = $fileStorageHelper;
    parent::__construct($context, $data);
}

Sie müssen also Ihren Konstruktor so aussehen lassen

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\MediaStorage\Helper\File\Storage\Database $fileStorageHelper,
    \Creare\Seo\Helper\Data $creareHelper,
    array $data = []
)
{
    $this->_creareHelper = $creareHelper;
    parent::__construct($context, $fileStorageHelper, $data);
}

Schlussfolgerung ...
In Ihren untergeordneten Klassen müssen Sie alle übergeordneten Klassenkonstruktorparameter sowie Ihre neuen Parameter angeben. Ich denke nicht, dass die Reihenfolge wichtig ist, und ich weiß nicht, was die beste Vorgehensweise ist.
Anschließend weisen Sie im Konstruktor Ihre neuen injizierten Objekte den Member-Variablen zu und rufen den übergeordneten Konstruktor mit der gleichen Anzahl von Parametern auf, die er benötigt.

Marius
quelle
2
Das macht Sinn, danke für deine Antwort. Ich hatte nur gehofft, es sei eleganter.
Adam Moss
Die Reihenfolge der Argumente in @Marius muss mit den Argumenten der übergeordneten Klasse __construct übereinstimmen. Ihre benutzerdefinierten Argumente müssen am Ende übergeben werden.
Chirag Dodia
@chiragdodia Warum? Ich glaube nicht. Alles, was ich bisher auf M2 erstellt habe, habe ich mit den zufällig hinzugefügten benutzerdefinierten Konstruktionsargumenten erstellt. Und es hat funktioniert. Die einzige Einschränkung besteht darin, dass die Argumente mit einem Standardwert zuletzt verwendet werden sollen.
Marius
@ Marius ja, es funktioniert in einigen Fällen, aber in meinem Fall, wenn ich \ Magento \ Catalog \ Block \ Product \ View habe, funktioniert es nicht, muss ich die gleiche Reihenfolge der Argumente wie im übergeordneten Konstruktor festlegen und zuletzt benutzerdefinierte Argumente hinzufügen. Schau dir meinen Code hier an magento.stackexchange.com/questions/95697/…
chirag dodia
Es funktioniert nicht bei mir, als ich versuchte, \ Magento \ Customer \ Block \ Form \ Register Block zu überschreiben
DEEP JOSHI