Service manager does not care if there's a factory or not

Hi!

It seems, that the service-manager doesn’t care anymore, if a service was initiated or not.

Example of my Module.php:


    public function getControllerConfig()
    {
        return [
            'factories' => [
                Brand\Controller\JsonDataController::class => function ($container) {
                    $ctrl = new Brand\Controller\JsonDataController();
                    $ctrl->setBrandTable($container->get(BrandTable::class));
                    return $ctrl;
                },
         ];
     }

But BrandTable was never initiated. Doesn’t this trigger an error, sth. like “Service not found. Are you sure you mapped it to factory?”

I’m confused.

Hey Malwon,

in this scenario BrandTable::class results into a string of the fully qualified classname. It is not an instance of the BrandTable object. The service manager may result into null in your case. This indicates, that you have registered BrandTable::class somewhere in your config already. You could solve this by type hinting the controller constructor method like the following example:

<?php

declare(strict_types=1);

namespace Marcel\Controller;

class MyController
{
    public function __construct(
        protected BrandTable $table
    ) {}

    ...
}

In this case the controller awaits an instance of BrandTable. If this is not given it will result into an error in any case.

1 Like

Hi ezkimo,

thanks for caring to answer.

You could solve this by type hinting the controller constructor method like the following example

I actually did type hinting.

This indicates, that you have registered BrandTable::class somewhere in your config already.

No, I didn’t.

I jut now tried the following to demonstrate what I mean:

This is my folder structure:
Screenshot_20230922_223320

My Module.php:

public function getControllerConfig()
    {
        return [
            'factories' => [
                Controller\IndexController::class => function ($container) {
                    $ctrl = new Controller\IndexController;
                    $ctrl->setFoo($container->get(Model\Foo::class));
                    return $ctrl;
                }
            ]
        ];
    }

My Controller:

class IndexController extends AbstractActionController
{

    protected Foo $foo;

    public function indexAction()
    {
        return new ViewModel();
    }

    /**
     * Set the value of foo
     *
     * @param Foo $foo
     *
     * @return self
     */
    public function setFoo(Foo $foo): self
    {
        $this->foo = $foo;

        return $this;
    }
}

This works! But actually it shouldn’t, cause I never provided a factory for my Foo-model.

Why doesn’t it throw this usual error:

Unable to resolve service “Application\Model\Foo” to a factory; are you certain you provided it during configuration?

:thinking:

Please check if an abstract factory is registered in your application which handles the creation of the class Foo. Search for abstract_factories in your code.

1 Like

@Tyrsson I don’t know why you deleted your post, because it’s the solution! Fortunately, your original reply is still readable. :smile: For some reason, I just must have pressed “yes” when the laminas-mvc installation-routine asked me about Laminas\Di.

Removing 'Laminas\Di' from config/modules.config.php helped. And now the error:

Unable to resolve service “Application\Model\Foo” to a factory; are you certain you provided it during configuration?

is thrown, as it is supposed to be, isn’t it?

Thank you man, and all others that posted their suggestions.

laminas-di comes with a registered abstract factory:

1 Like

@malwon, This error-solving technique has really made someone a real deep-thinking developer. Now, someone can build an entire framework on his own or even a module in Laminas MVC. This is really helpful. Thanks!

1 Like

Can’t remember why I removed it…

Lamians-Di has caused many issues like this. It caused me a major issue using Laminas-Authentication since it autowired an instance when laminas-auth does not provide a factory. Honestly, in my opinion it should be removed from the list of dependencies that is offered in the create-project routine.

1 Like

Please create an issue report or a pull request for it, otherwise your opinion will be lost.

2 Likes