Simple example of DI autowiring in Laminas MVC

Hey guys,

I am reading in the docs that Laminas-DI supports autowiring out of the box. So if understand that correctly, I should not need any configuration and classes should be injected via contructors right away. However that is not the case :slight_smile:
Are my expectations correct?
In other frameworks like Laravel or Symfony, if I create a new class and I pass it to a constructor of another class it just gets injected. Does it work the same in Laminas?
Can you point me to some minimal example? I have already tried but most of the examples I find are either explicitly defining the dependencies or are using an abstract factory concept.

In another words I would like to get rid of the following code in my Module.php :slight_smile:

public function getControllerConfig(): array
    {
        return [
            'factories' => [
                Controller\AdvertController::class => function($container) {
                    return new Controller\AdvertController(
                        $container->get(Model\AdvertTable::class)
                    );
                },
            ],
        ];
    }

    public function getServiceConfig(): array
    {
        return [
            'factories' => [
                Model\AdvertTable::class => function($container) {
                    $dbAdapter = $container->get(AdapterInterface::class);
                    $resultSetPrototype = new ResultSet();
                    $resultSetPrototype->setArrayObjectPrototype(new Model\Advert());
                    $tableGateway = new TableGateway('advert', $dbAdapter, null, $resultSetPrototype);
                    return new Model\AdvertTable($tableGateway);
                }
            ],
        ];
    }

I am kind of evaluating Laminas/Mezzio (among other frameworks) as a candidate to rewrite a ZF1 application but my daily bread is C# or .NET so I know concepts like DI but have not really used them in PHP or Laminas so I might be missing something really elementary.

Thanks a lot

Hello and welcome to our forums! :smiley:

If I follow your code examples, you don’t need laminas-di.

Sure, use the reflection-based factory of laminas-servicemanager which is already present in a laminas-mvc application. For your controller example this means:

return [
    'factories' => [
        Controller\AdvertController::class => \Laminas\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory::class,
    ],
];

The second example contains some more preparation therefore a separate factory class is recommended here. Then the configuration can also be cached.

You can find more examples of the usage of the reflection-based factory in the tutorials:

Then Mezzio is the right candidate, because it has a low entry and can handle the migration from ZF1. See:

Hey @froschdesign,

thanks a lot for your input.

So if I am correct even if I use the reflection-based factory I need to explicitly configure it for every single class or can I make the reflection-based factory a default or something like that to achieve the behavior of other frameworks where it just works out of the box?

Sure, I understand that in cases like the second example (the one with more preparation) the specific factory makes sense and is the only reasonable option. But I actually don’t like the code of the second example I just put it here since it is present in the docs. I mean imagine having more tables in DB (which is quite an expected scenario I would say) it does not make much sense to me to have such a complicated factory for each model/table gateway like that. I would definitively look for another option in this case.

Yeah, I have googled a lot and Mezzio seems to be quite a good choice to migrate from ZF1 using the strangler pattern. But to be honest since migration from ZF1 means a sort of complete rewrite anyway that puts other (non Laminas) frameworks into play to. And I must say I am kind of twisted here. I mean I like the idea of having everything under my control in Laminas/Mezzio as opposed to other “magical” frameworks. On the other hand I also see the benefit there as one do not have to define everything as it gets tedious and repetitive.

I hope I was able to express myself in a way that is understandable and clear. Thanks again for your response. I will probably spend some more time evaluating :slight_smile:

Of course you can, register it as an abstract factory:

use Laminas\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory;

return [
    'service_manager' => [
        'abstract_factories' => [
            ReflectionBasedAbstractFactory::class,
        ],
    ],
    // …
];

Another option is to use a CLI command to create a factory. Is also better for the performance.
(Version 4 of laminas-servicemanager will bring more).

It is quite simple: do not use laminas-db. :smile:
I don’t use it either, it’s too complicated.

1 Like

I can recommend the following library if you are interested in autowiring for Laminas and Mezzio:

1 Like

Thanks a lot. It always takes some time to understand the philosophy behind the framework :slight_smile:

Btw I am probably weird but I do not like Doctrine either. What I really like is the good old Zend_Db_Select stuff enhanced with hydrators to get typed objects instead of arrays.

Thanks for the library tip, that looks interesting.

The same works with laminas-db:

But why use a library that does not support relationships? :man_shrugging:t2:

But why use a library that does not support relationships? :man_shrugging:t2:

That would be another discussion :slight_smile: