DI i rozszerzenie bloku w Magento 2

15

Wydaje mi się, że staram się uchwycić wstrzykiwanie zależności Magento 2 za pomocą bloków, za każdym razem, gdy próbuję rozszerzyć blok, który nie jest \ Magento \ Framework \ View \ Element \ Template, mam błędy.

Chcę utworzyć blok, który rozszerza bardzo podstawową klasę bloków Magento \ Theme \ Block \ Html \ Header \ Logo - wszystko działa dobrze, dopóki nie spróbuję wstrzyknąć zależności w ramach metody konstruowania:

<?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);
    }
}

Jak tylko spróbuję wstrzyknąć moją klasę pomocnika (lub cokolwiek innego w tym zakresie, otrzymuję ślad stosu zaczynający się od następującego błędu:

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

Jeśli dodam te same zależności do mojego __construct, jak plik, który z niego rozszerzam, działa, ale na pewno jest to wsteczny sposób robienia rzeczy, ponieważ punktem dziedziczenia klas jest to, że wchłaniam wszystkie metody i właściwości rodzica?

Wydaje mi się, że potrzebuję tylko podstawowego wyjaśnienia od kogoś na temat wychodzenia z zajęć i korzystania z DI w Magento 2. Każda pomoc bardzo doceniana!

Adam Moss
źródło
„z pewnością jest to zacofany sposób”, zgodził się.
James

Odpowiedzi:

19

Klasa, którą próbujesz rozszerzyć, ma tego konstruktora:

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);
}

więc musisz sprawić, by twój konstruktor wyglądał tak

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);
}

Wniosek ...
W swoich klasach podrzędnych musisz określić wszystkie parametry konstruktora klasy nadrzędnej oraz nowe parametry. Nie sądzę, żeby kolejność była ważna i nie wiem, jaka jest najlepsza praktyka.
Następnie w konstruktorze przypisujesz nowe wstrzyknięte obiekty do zmiennych członkowskich i wywołujesz konstruktor nadrzędny z taką samą liczbą wymaganych parametrów.

Marius
źródło
2
To ma sens, dziękuję za twoją odpowiedź. Chyba po prostu miałem nadzieję, że to będzie bardziej eleganckie.
Adam Moss,
@Marius kolejność argumentów musi być taka sama jak argumentów metody nadrzędnej __construct, argumenty niestandardowe należy przekazać na końcu.
chirag dodia
@chiragdodia Dlaczego? Nie wydaje mi się Wszystko, co do tej pory zbudowałem na M2, zbudowałem przy użyciu niestandardowych argumentów konstrukcji losowo dodanych. I zadziałało. jedynym ograniczeniem jest to, że argumenty o wartości domyślnej powinny iść na końcu.
Marius
@Marius tak działa w niektórych przypadkach, ale w moim przypadku, gdy mam rozszerzenie \ Magento \ Catalog \ Block \ Product \ View nie działa, muszę zrobić taką samą kolejność argumentów jak w konstruktorze nadrzędnym i w końcu dodać niestandardowe argumenty. Spójrz na mój kod tutaj magento.stackexchange.com/questions/95697/…
chirag dodia
Nie działa dla mnie, gdy próbowałem zastąpić \ Magento \ Customer \ Block \ Form \ Register Block
DEEP JOSHI