DI и расширение блока на Magento 2

15

Кажется, мне трудно понять внедрение зависимостей в Magento 2 с помощью блоков, каждый раз, когда я пытаюсь расширить блок, который не является \ Magento \ Framework \ View \ Element \ Template, я получаю ошибки.

Я хочу создать блок, который расширяет базовый класс блоков Magento \ Theme \ Block \ Html \ Header \ Logo - все работает нормально, пока я не попробую внедрить зависимости внутри метода construct:

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

Как только я пытаюсь внедрить свой вспомогательный класс (или что-нибудь еще в этом отношении, я получаю трассировку стека, начиная со следующей ошибки:

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

Если я добавлю к своей __construct те же зависимости, что и файл, который я расширяю, он будет работать, но, безусловно, это обратный путь, так как смысл наследования класса заключается в том, что я поглощаю все методы и свойства родителя?

Я думаю, что мне просто нужно получить базовое объяснение от кого-то о расширении уроков и использовании DI с Magento 2. Любая помощь очень ценится!

Адам Мосс
источник
«Конечно, это обратный способ делать вещи» Согласен.
Джеймс

Ответы:

19

Класс, который вы пытаетесь расширить, имеет этот конструктор:

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

так что вам нужно, чтобы ваш конструктор выглядел так

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

Заключение ...
В ваших дочерних классах вам нужно указать все параметры конструктора родительского класса плюс ваши новые параметры. Я не думаю, что порядок важен, и я не знаю, какова лучшая практика.
Затем в конструкторе вы присваиваете новые внедренные объекты элементам vars и вызываете родительский конструктор с тем же количеством параметров, которое требуется.

Мариус
источник
2
Это имеет смысл, спасибо за ваш ответ. Наверное, я просто надеялся, что это будет более элегантно, чем это.
Адам Мосс
Порядок аргументов @Marius должен совпадать с аргументами метода родительского класса __construct, ваши пользовательские аргументы должны быть переданы в конце.
Чираг Додиа
@chiragdodia Почему? Я так не думаю. Все, что я построил до сих пор на M2, я построил, используя произвольно добавленные аргументы пользовательской конструкции. И это сработало. единственным ограничением является то, что аргументы со значением по умолчанию должны идти последними.
Мариус
@Marus: Да, он работает в некоторых случаях, но в моем случае, когда у меня расширение \ Magento \ Catalog \ Block \ Product \. Просмотр не работает, мне нужно сделать тот же порядок аргументов, что и в родительском конструкторе, и наконец добавить собственные аргументы. Взгляните на мой код здесь magento.stackexchange.com/questions/95697/…
chirag dodia
Это не работает для меня, когда я пытался переопределить \ Magento \ Customer \ Block \ Form \ Register Block
DEEP JOSHI