Magento – Magento 2 – Inject arguments into constructors of fabricated objects

magento-2.1magento2object-manager

When we are using a SDK third party library of any service we can not change it and when this service requires a parameter as argument. Example:

/**
 * @param string $apiKey
 * @param int|null $timeout
 */
public function __construct($apiKey, $timeout = null)
{
    $this->client = new Client(
        new GuzzleClient(
            [
                'base_url' => 'https://api.urlapi/'
            ]
        ),
        $apiKey,
        $timeout
    );
}

In a custom module, we need to take this apiKey from a configuration and pass it as an argument in the creation of this object.

I would not like to instantiate with "new" of course, because of the high coupling.

My solution so far was to fabricate this object via Magento:

<?php
namespace MyVendor\MyModule\Model;

use ServiceVendor\Sdk\ClassNameFactory; // Create automatically

class MyModelExample
{
     protected $classNameFactory;

     public function __construct(
        ClassNameFactory $classNameFactory
     ){
         $apiKey = ''; // Get my apiKey from any other method.
         $this->classNameFactory = $classNameFactory->create([
             'apiKey' => $apiKey
         ]);
     }
}

This works fine in developer mode when we do not run the command:

bin/magento setup:di:compile

Because the create method of the \Magento\Framework\ObjectManager\Factory\Dynamic\Developer class is executed and the _resolveArguments method resolves this argument injection.

But if we run the command:

bin/magento setup:di:compile

This stops working because it is executed by the create method of the class: \Magento\Framework\ObjectManager\Factory\Compiled

And instead of injecting the apiKey argument an ObjectManager instance is injected. I think there is something missing for the di.xml file to work correctly.

It only works for both cases, if I pass with the key "0" of the array as well:

$this->classNameFactory = $classNameFactory->create([
     0 => $apiKey,
     'apiKey' => $apiKey
]);

I understand that even if it's working that way, it's not the best way to do it, and to ensure it's easy to create tests.

What do you suggest for the best way to work with this?

Thanks

Best Answer

Something like this maybe ?

$this->flagFactory->create(['data' => ['flag_code' => 'something']]);

How can data parameters be passed to a factory create( ) in Magento 2?

Related Topic