# "Laminas-DI" parameter resolver misunderstanding

**URL:** <https://discourse.laminas.dev/t/laminas-di-parameter-resolver-misunderstanding/1509>\
**Category:** Components & MVC\
**Tags:** laminas-di\
**Created:** [April 7, 2020, 11:05am UTC](https://discourse.laminas.dev/t/laminas-di-parameter-resolver-misunderstanding/1509 "2020-04-07T11:05:32Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Andriy\_Lozinsky](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/andriy_lozinsky/32/59_2.png) [@Andriy\_Lozinsky](https://discourse.laminas.dev/u/Andriy_Lozinsky)\
**Post date:** [April 7, 2020, 11:05am UTC](https://discourse.laminas.dev/t/laminas-di-parameter-resolver-misunderstanding/1509/1 "2020-04-07T11:05:32Z")

</div>

Hi everyone.  
Firstly, sorry for my bad English.

I am currently investigating “Laminas” components working in conjunction with “Mezzio”. My general work related to Magento framework and there is a great feature which related to dependencies management. I mean virtual types. In short Virtual types are ability to create multiple instances of the same class with different constructor parameters.

I’ve found in laminas something simillar. In “Laminas-Di” documentation I found this example:

```
use Laminas\Di\Injector;
use Laminas\Di\Config;

$injector = new Injector(new Config([
    'preferences' => [
        FooInterface::class => Foo::class,
    ],
    'types' => [
        'MyClass.A' => [
            'typeOf' => MyClass::class,
            'preferences' => [
               FooInterface::class => SpecialFoo::class,
            ],
        ],
        'MyClass.B' => [
            'typeOf' => MyClass::class,
            'preferences' => [
               FooInterface::class => Bar::class,
            ],
        ],
    ],
]));

```

In my case I need make two instances of \Mezzio\LaminasView\LaminasViewRenderer. LaminasViewRenderer has the next constructor specification:

`public function __construct(RendererInterface $renderer = null, $layout = null, string $defaultSuffix = null)`

I need that the $renderer param will be resolved using psr container, $layout must be ‘admin::layout’ and $suffix may be null for viewRenderer of admin part and the same things for viewRenderer of public part, but $layout must be ‘default::layout’.

inside Admin\ConfigProvider I’ve placed next code:

```
class ConfigProvider
{
    public function __invoke(): array
    {
        return [
            'dependencies' => $this->getDependencies(),     
        ];
    }

    public function getDependencies(): array
    {
        return [
            'auto' => [
                'types' => [
                    TemplateRenderer\AdminTemplateRendererInterface::class => [
                        'typeOf' => \Mezzio\LaminasView\LaminasViewRenderer::class,
                        'parameters' => [
                            'renderer' => '*',
                            'layout' => 'admin::layout',
                            'defaultSuffix' => '*',
                        ]
                    ]
                ]
            ]
        ];
    }

```

I expected that I get LaminasViewRenderer instance with ‘admin::layout’ predefined parameter inside auto generated factory. But after I run di-generate-aot (as discribed here [https://docs.laminas.dev/laminas-di/cookbook/aot-guide/](https://docs.laminas.dev/laminas-di/cookbook/aot-guide/)) script I’ve got next factories class code:

```
final class AdminTemplateRendererInterfaceFactory implements FactoryInterface
{
    public function create(ContainerInterface $container, array $options = [])
    {
        $args = empty($options)
            ? [
                null, // renderer
                null, // layout !!! I expected that 'admin::layout' string be here
                null, // defaultSuffix
            ]
            : [
                array_key_exists('renderer', $options) ? $options['renderer'] : null,
                array_key_exists('layout', $options) ? $options['layout'] : null,
                array_key_exists('defaultSuffix', $options) ? $options['defaultSuffix'] : null,
            ];

        return new \Mezzio\LaminasView\LaminasViewRenderer(...$args);
    }

```

I spent some time for debugging and found out that when DependencyResolver try to configure injection then it search configured params using class name which pointed at the typeOf.  
I am not sure but it seems to me a “layout” parameter should be searched by alias to get right result. Currently it returns nothing because there is no key with a LaminasViewRenderer type. And it not make sense. I need create different instances of LaminasViewRenderer that why I used aliases. And then I will get this instances by their aliases.

 ![2020-04-07_13-31](https://canada1.discourse-cdn.com/flex032/uploads/zendframework/original/1X/c8b09a2c3e176a0205cd8a0756ff0a8ee238586f.png)

hope I explained well.

Please explain. Am I doing somethink wrong or maybe it is a wrong behaviour of the dependency params resolver?  
Great thanks.

---

<div class="post-metadata">

**Author:** ![tux-rampage](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/tux-rampage/32/237_2.png) [@tux-rampage](https://discourse.laminas.dev/u/tux-rampage)\
**Post date:** [April 8, 2020, 1:21pm UTC](https://discourse.laminas.dev/t/laminas-di-parameter-resolver-misunderstanding/1509/2 "2020-04-08T13:21:08Z")

</div>

It seems that your Config is not present when the AoT compiler is running. With your config the expected factory should look like this:

```
final class AdminTemplateRendererInterfaceFactory implements FactoryInterface
{
    public function create(ContainerInterface $container, array $options = [])
    {
        $args = empty($options)
            ? [
                $container->get(\Laminas\View\RendererInterface::class), // renderer
                'admin::layout',
                '*',
            ]
            : [
                array_key_exists('renderer', $options) ? $options['renderer'] : $container->get(\Laminas\View\RendererInterface::class),
                array_key_exists('layout', $options) ? $options['layout'] : 'admin::layout',
                array_key_exists('defaultSuffix', $options) ? $options['defaultSuffix'] : '*',
            ];

        return new \Mezzio\LaminasView\LaminasViewRenderer(...$args);
    }

```

The `"*"` for `defaultSuffix` will not work as you may expect it here. As documented here: [https://docs.laminas.dev/laminas-di/config/#parameters](https://docs.laminas.dev/laminas-di/config/#parameters) then special `"*"` will **only** work for parameters that have a class or interface typehint, but `$defaultSuffix` is `string`.

Also your `$renderer` is allowed to be null. That means the resolver will resolve to `null` when the resolved parameter is not available via the psr container (i.e. `$container->has(RendererInterface::class) === false`). Does your PSR container provide a `RendererInterface::class` service?

You should also type hint the `$layout` parameter as string or use `ValueInjection()` in the di config to avoid accidential container lookups.

---

<div class="post-metadata">

**Author:** ![tux-rampage](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/tux-rampage/32/237_2.png) [@tux-rampage](https://discourse.laminas.dev/u/tux-rampage)\
**Post date:** [April 8, 2020, 1:42pm UTC](https://discourse.laminas.dev/t/laminas-di-parameter-resolver-misunderstanding/1509/3 "2020-04-08T13:42:57Z")

</div>

@Andriy_Lozinsky is it possible to share the piece of you project for further investigation? Oh and thanks for the detailed information, of course.

---

<div class="post-metadata">

**Author:** ![Andriy\_Lozinsky](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/andriy_lozinsky/32/59_2.png) [@Andriy\_Lozinsky](https://discourse.laminas.dev/u/Andriy_Lozinsky)\
**Post date:** [April 9, 2020, 8:32am UTC](https://discourse.laminas.dev/t/laminas-di-parameter-resolver-misunderstanding/1509/4 "2020-04-09T08:32:53Z")

</div>

@tux-rampage yes, please:

> **[loz-a/easyng](https://github.com/loz-a/easyng/tree/master)**
>
> Contribute to loz-a/easyng development by creating an account on GitHub.

  
This is a small pet project which I started in order to experiment with Laminas-Di.  
Please let me know if you will get some results. I am very interesting these “Laminas-Di” stuffs

---

<div class="post-metadata">

**Author:** ![Andriy\_Lozinsky](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/andriy_lozinsky/32/59_2.png) [@Andriy\_Lozinsky](https://discourse.laminas.dev/u/Andriy_Lozinsky)\
**Post date:** [April 12, 2020, 5:51pm UTC](https://discourse.laminas.dev/t/laminas-di-parameter-resolver-misunderstanding/1509/5 "2020-04-12T17:51:58Z")

</div>

@tux-rampage I continue to investigate this problem and found out that if I used interface as alias it’s not working as I expected. The thing is that when “generate” method is called then first one it generate factories for generic classes, the second one it generate fectories for “configured types” classes. And if we use some interface for type alias after the first generating the factory for this interface factories has already been generated, and exists in factories cache. In second generating in which typed parameters must be filled from “typed config” this factory just returned from cache without generating process and filled config params.

 ![2020-04-12_20-34](https://canada1.discourse-cdn.com/flex032/uploads/zendframework/original/1X/33cc4fcd1e66c76b168a29c11434e05ad64d9c88.png)  
I solved this problem replaced Interface to constant of this interface:

```auto
interface AdminTemplateRendererInterface extends \Mezzio\Template\TemplateRendererInterface
{
    public const DI_ALIAS = 'Easy\Admin\Admin\TemplateRenderer\AdminTemplateRenderer';
}

```

```auto
public function getDependencies(): array
    {
        return [
            'auto' => [
                'types' => [
                    TemplateRenderer\AdminTemplateRendererInterface::DI_ALIAS => [
                        'typeOf' => \Mezzio\LaminasView\LaminasViewRenderer::class,
                        'preferences' => [
                            \Laminas\View\Renderer\RendererInterface::class => \Laminas\View\Renderer\PhpRenderer::class,
                        ],
                        'parameters' => [
                            'layout' => 'admin::layout',
                        ]
                    ]
                ]
            ]
        ];
    }

```

but that didn’t solve my problem definitelly. So I kept investigating. I noticed that if I change $className param to $class when calling resolveParameters method then all works well and I got factorie which I expected.

 ![2020-04-12_01-03](https://canada1.discourse-cdn.com/flex032/uploads/zendframework/original/1X/0c35406c37f1e02445842bb74d61dd1aa5491f76.png)

so my current config looks like:

```auto
return [
            'auto' => [
                'types' => [
                    TemplateRenderer\AdminTemplateRendererInterface::DI_ALIAS => [
                        'typeOf' => \Mezzio\LaminasView\LaminasViewRenderer::class,
                        'preferences' => [
                            \Laminas\View\Renderer\RendererInterface::class => \Laminas\View\Renderer\PhpRenderer::class,
                        ],
                        'parameters' => [
                            'layout' => 'admin::layout',
                        ]
                    ]
                ]
            ]
        ];

```

and the result factory is:

```auto
final class AdminTemplateRendererFactory implements FactoryInterface
{
    public function create(ContainerInterface $container, array $options = [])
    {
        $args = empty($options)
            ? [
                $container->get('Laminas\\View\\Renderer\\PhpRenderer'), // renderer
                'admin::layout', // layout
                null, // defaultSuffix
            ]
            : [
                array_key_exists('renderer', $options) ? $options['renderer'] : $container->get('Laminas\\View\\Renderer\\PhpRenderer'),
                array_key_exists('layout', $options) ? $options['layout'] : 'admin::layout',
                array_key_exists('defaultSuffix', $options) ? $options['defaultSuffix'] : null,
            ];

        return new \Mezzio\LaminasView\LaminasViewRenderer(...$args);
    }

```
