6

I have a M1 module that I'm looking at porting to M2, and part of one of helpers contains code that looks like this:

public function getModel($code)
{
     return Mage::getSingleton('vendor/package_model_' . $code);
}

Given that Magento 2 uses dependency injection, I know that I can specify that I'd like an instance of \Vendor\Package\Model\Interface, but how can I specify that I'd like a specific model?

I'd like to follow best practice, so if it's possible to avoid doing this directly through the ObjectMananger then that would be ideal, but if that's the only option then that's OK too.

scrowler
  • 2,014
  • 1
  • 18
  • 42

3 Answers3

1

Try to get rid of this shortcut method and use dependency injection to get the actual classes you need where you previously used this.

Fabian Schmengler
  • 65,791
  • 25
  • 187
  • 421
  • Hey Fabian - thanks for the answer. In this particular scenario it needs to be dynamic somehow at least, because the model name depends on the first two characters of a voucher code that gets entered by the user - is there a way that can be achieved before call time? – scrowler Mar 10 '16 at 23:04
  • 1
    I think I would create an own factory class in this case and not let Magento instantiate these dynamic classes – Fabian Schmengler Mar 10 '16 at 23:09
  • I like this approach! – scrowler Mar 10 '16 at 23:09
1

I hope the code below will help you:

public function __construct(
    \Magento\Framework\ObjectManagerInterface $objectManager
) {
    $this->objectManager = $objectManager;
}

public function getModel($code)
{
    $modelins = '\Vendor\Package\Model\\' . $code;
    return $this->objectManager->get($modelins);
}
Morgy
  • 101
  • 7
Pradeep Kumar
  • 8,731
  • 12
  • 60
  • 86
  • Hi Pradeep. I know how to use the object manager to achieve this - but I have read that using it is not good practice, and since I am new to Magento 2 I was wondering if there is a better way to achieve this. – scrowler Dec 16 '15 at 03:57
  • On a side note, what is $layersPool for? Also vendor/package_model_xxx won't work, would need to be $modelins = 'Vendor\Package\Model\\' . $code; yeah? – scrowler Dec 16 '15 at 04:02
  • 1
    @Robbie :- using \Magento\Core\Model\ObjectManager::getInstance() is bad way , init the object manager and get ur model is fine http://magento.stackexchange.com/questions/10517/instantiating-helpers-in-magento-2 – Pradeep Kumar Dec 16 '15 at 04:32
  • Great- thanks very much for the explanation. Obviously using DI is preferable where possible though? – scrowler Dec 16 '15 at 04:38
  • Could you add a bit of an explanation in your answer for this? – scrowler Dec 16 '15 at 04:39
  • @Robbie, you're right it should be $modelins='\Vendor\Package\Model\' . $code I think $layersPool is not for this example – Arkadii Chyzhov Dec 17 '15 at 17:46
  • if we implement the code using Di that is in di.xml there will one reader class pass all dynamic class to as param object , in reader class based on param return the object if you do like this when you call that reader class in any other function it init all the class and return which you needed it, why should you want to init all class ? did you solve this solution please share the solution i also have some issue – Pradeep Kumar Oct 27 '17 at 09:22
  • i hope you read my prev comment and also you mentioned layersPool there also inside the layersPool they used object manger to load the class – Pradeep Kumar Oct 27 '17 at 09:26
0

Finally I got the answer for how to call class from in DI.

It can be done by using factory in DI and in reader use create() it will be something like this:

<type name="Magento\Catalog\Model\Layer\Resolver">
    <arguments>
        <argument name="layersPool" xsi:type="array">
            <item name="category" xsi:type="string">Magento\Catalog\Model\Layer\CategoryFactory</item>
            <item name="search" xsi:type="string">Magento\Catalog\Model\Layer\SearchFactory</item>
        </argument>
    </arguments>
</type>

In reader file use:

public function create($layerType)
{
    return $this->layersPool[$layerType]->create();
}

So without ObjectManager we can call dynamic class from DI.

Morgy
  • 101
  • 7
Pradeep Kumar
  • 8,731
  • 12
  • 60
  • 86