2

I'm under the impression that we can inject data into classes using di.xml and the $data array dependency. I'm struggling with getting it working however. Am I not understanding the concept correctly? Or am I missing some configuration?

Below is my (simplified) code.

etc/frontend/di.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="DannyNimmo\Subcategories\Block\ListCategory">
        <arguments>
            <argument xsi:type="array" name="data">
                <item xsi:type="string" name="test">test</item>
            </argument>
        </arguments>
    </type>
</config>

Block/ListCategory.php:

<?php

namespace DannyNimmo\Subcategories\Block;

class ListCategory
    extends \Magento\Framework\View\Element\Template
    implements \Magento\Framework\DataObject\IdentityInterface
{

    public function __construct (
        \Magento\Framework\View\Element\Template\Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
        var_dump($data);
    }

}

Edit: I should say that I am seeing an empty array array(0) { } as the output.

Danny Nimmo
  • 1,243
  • 1
  • 10
  • 21

1 Answers1

0

I can't test your code at the moment to solve your issue but I'd like to add something that can be useful.

DI is intended to pass injectables, that are classes that encapsulate some logic. DI shouldn't be used to pass data, the so called newables.

For example, if you need the data you are trying to inject, you should instead inject a class that is responsible of retrieving that data. This kind of classes are called repositories. In some circumstances it's better to use factories.

You can read more here.

Enjoy.

Alessandro Ronchi
  • 3,746
  • 1
  • 23
  • 28
  • Are you sure? For example: there are multiple session managers. Each instance use custom session namespace ( like in Magento). Are you think, that we need to hardcode all namespaces in services ( SessionNamespaceProvider for example ) instead of setup namespaces values via di.xml? – Max Feb 12 '17 at 10:28
  • In this case I was wanting to inject via DI for customisability, i.e. data can be easily added by another module. What is your opinion on the purpose of $data in this case? – Danny Nimmo Feb 12 '17 at 11:06
  • @danny you can also set data values using layout configuration (attributes tag in block declaration) – Max Feb 12 '17 at 13:50
  • Sorry @Max I don't understand your point. The di.xml is the "default" mapping between an interface declaration (the one you pass to the constructor) and the actual class you want to instantiate. It's ok to use di.xml to change that mapping for session managers that are a perfect example of injectables. – Alessandro Ronchi Feb 13 '17 at 07:00
  • Hi @DannyNimmo I don't like the idea of passing data via di.xml; so said feel free to use the framework the way you prefer. – Alessandro Ronchi Feb 13 '17 at 07:02
  • @Alessandro we are talking about the data, which used for setup any services via di.xml. By your opinion, we can use only objects for setup services. But Magento di.xml configuration provide broader settings than base "Dependency Injection" concept (for example "plugin", "virtualTypes"). You can setup your models via di.xml using many data types, not only objects (string, boolean, array), moreover this possibility is actively used by magento core. Try to find xsi:type="string|array|boolean" in core di.xml files. – Max Feb 13 '17 at 08:00
  • About question: i think, that author does not need to setup newable(product, category, store) in data, maybe it is view_mode, column_count, container_css_class, which can be changed by other dependend modules – Max Feb 13 '17 at 08:00
  • i am not adherent of setuping blocks using di.xml, but it is possible. I will remoind, that for setuping data can be used arguments tag in layout configuration. – Max Feb 13 '17 at 08:04
  • The di.xml is the "default" mapping between an interface declaration (the one you pass to the constructor) and the actual class you want to instantiate. not only – Max Feb 13 '17 at 08:11
  • Ok @max, got it, thank you for your explanation. – Alessandro Ronchi Feb 13 '17 at 10:29