4

I am trying to create a "service" in my module's di.xml file for a third-party vendor object.

I tried to configure it like this:

<type name="League\Flysystem\MountManager">
    <arguments>
        <argument name="filesystems" xsi:type="array">
            <item name="orders_storage" xsi:type="object">oneup_flysystem_orders_storage_filesystem</item>
            <item name="tmp_storage" xsi:type="object">oneup_flysystem_tmp_storage_filesystem</item>
        </argument>
    </arguments>
</type>

But anytime I would run setup:di:compile and inject this service into my class, Magento throws an exception, because the arguments that I defined did not get passed to the factory that creates the object, so the code does a fallback and injects the ObjectManager as the first argument to the constructor.

I was able to get around this issue by creating a dummy class inside my module that does nothing but extend the class I want to override, like this:

<?php

namespace Renegade\FileStorage\Manager;

use League\Flysystem\MountManager as BaseMountManager;

/**
 * Class MountManager
 *
 * @package Renegade\FileStorage\Manager
 */
class MountManager extends BaseMountManager
{
}

Then creating a preference node for the class in di.xml:

<preference for="League\Flysystem\MountManager" 
            type="Renegade\FileStorage\Manager\MountManager"/>

And finally changing my type from:

<type name="League\Flysystem\MountManager">

To:

<type name="Renegade\FileStorage\Manager\MountManager">

From what I can tell, doesn't seem to work on objects that are outside of the Magento application. If that's not the case, can someone tell me how to accomplish this without my workaround?

1 Answer 1

2

There is 2 approaches available to do this:

It is strongly recommended to use the adapter pattern to reduce the change impact on your code if API changes happen.

I will only describe how-to use directly the third party library, the other method is explained in the documentation.

Let's say you have a service A (your service) in which you want to inject the service B (the MountManager service) using your custom parameters.

For the example, let's say our service A is the following class:

namespace Vendor\Module\Model;

class MyServiceA {

    protected $mountManager;

    public function __construct(\League\Flysystem\MountManager $mountManager)
    {
        $this->mountManager = $mountManager;
    }
}

You need to first declare the service B as a virtual type in your di.xml like below:

<virtualType name="mountManager" type="League\Flysystem\MountManager">
    <arguments>
        <argument name="filesystems" xsi:type="array">
            <item name="orders_storage" xsi:type="object">oneup_flysystem_orders_storage_filesystem</item>
            <item name="tmp_storage" xsi:type="object">oneup_flysystem_tmp_storage_filesystem</item>
        </argument>
    </arguments>
</virtualType>

Then, you are good to configure your service A:

<type name="Vendor\Module\Model\MyServiceA">
    <arguments>
        <argument name="mountManager" xsi:type="object">mountManager</argument>
    </arguments>
</type>

And, voilà.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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