15

I seem to be struggling to grasp Magento 2 dependency injection with blocks, every time I try to extend a block that isn't \Magento\Framework\View\Element\Template I end up with errors.

I want to create a block that extends the very basic block class of Magento\Theme\Block\Html\Header\Logo - everything works fine until I try dependency injection within the construct method:

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

As soon as I try to inject my helper class (or anything else for that matter, I get a stack trace starting with the following error:

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

If I add the same dependencies to my __construct as the file I'm extending from it works, but surely that's a backwards way of doing things as the point of class inheritance is that I absorb all of the parent's methods and properties?

I think I just need a basic 101 explanation from someone on extending from classes and using DI with Magento 2. Any help much appreciated!

  • "surely that's a backwards way of doing things" Agreed. – James Apr 12 '16 at 15:24
19

The class you are trying to extend has this constructor:

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

so you need to make your constructor look like this

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

Conclusion...
In your child classes you need to specify all the parent class constructor params plus your new params. I don't think the order is important, and I don't know what the best practice is.
Then in the constructor you assign your new injected objects to member vars and call the parent constructor with the same number of parameters it requires.

  • 2
    That makes sense thanks for your answer. I guess I was just hoping it was more elegant than that. – Adam Moss Jul 16 '15 at 8:28
  • @Marius order of arguments needs to same as parent class __construct method arguments, your custom arguments need to pass at the end. – chirag dodia Jan 4 '16 at 6:26
  • @chiragdodia Why? I don't think so. Everything I built so far on M2 I built using the custom construct arguments randomly added. And it worked. the only constraint is that the arguments with a default value should go last. – Marius Jan 4 '16 at 7:17
  • @Marius yes its working in some of cases but in my case when i have extend \Magento\Catalog\Block\Product\View its not working i need to make same order of arguments as in parent constructor and added custom arguments at last. Take a look at my code here magento.stackexchange.com/questions/95697/… – chirag dodia Jan 4 '16 at 7:55
  • It is not working for me when I tried to override \Magento\Customer\Block\Form\Register Block – DEEP JOSHI Jan 23 '18 at 6:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.