madeye
madeye

Reputation: 1406

Correct way to use service manager in Zend3

I was reading Zend 3 documentation on Service Manager and i got this problem.

In documentation it says that if we have some DI in our controller we should update module.config.php file and add controllers key and invoke controller not with InvokableFactory::class but with custom factory class and add another key service_manager that contains array of classes that my first controller uses.

Ok so i do that:

module.config.php

'service_manager' => [
        'factories' => [
            Controller\Controller2::class => Factory\Controller2Factory::class,
            Controller\Controller3::class => Factory\Controller3Factory::class,
        ],
    ],
'controllers' => [
        'factories' => [
            Controller\Controller1::class => Factory\Controller1Factory::class
        ],
    ]

Controller1Factory.php

class Controller1Factory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        return new Controller1(
            $container->get(Controller2::class),
            $container->get(Controller3::class),
        );
    }
}

But now i have error that Controller2 and Controller3 also have DI in their constuctors, so i make new custom factories and so on and so on...until i get to my models.

And Models also have Dependency that is injected in their controller which is zend native \Zend\Db\TableGateway\TableGatewayInterface and i now have to edit my conf file again and add TableGatewayInterface.

And that is wrong. I should never be forced to inject native zend classes and services this way.

So what am i doing wrong?

Upvotes: 0

Views: 500

Answers (1)

Al Foиce    ѫ
Al Foиce ѫ

Reputation: 4315

If your Controller has no dependency, it's the best way to declare it in module.config.php as you did.

But if it has dependecies, it's better to do it in Module.php. You first declare your services, then the controller (don't forget to remove it from module.config.php), injecting in it the services it depends :

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

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

And in your controller:

private $table;

public function __construct(MyObjectTable $table)
{
    $this->table = $table ;
}

It is described in This ZF3 tutorial page and following.

Upvotes: 1

Related Questions