ServiceManager in ZF3

5.6k views Asked by At

I know that this has been covered extensively in other threads, but I'm struggling to work out how to replicate the effect of $this->getServiceLocator() from ZF2 controllers in ZF3 ones.

I have tried creating a factory using the various other answers and tutorials that I've found here and elsewhere, but ended up in a mess with each of them, so I'm pasting my code as it was when I started in the hope that someone can point me in the right direction?

From /module/Application/config/module.config.php

'controllers' => [
    'factories' => [
        Controller\IndexController::class => InvokableFactory::class,
    ],
],

From /module/Application/src/Controller/IndexController.php

public function __construct() {
    $this->objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
    $this->trust = new Trust;
}
2

There are 2 answers

3
tasmaniski On BEST ANSWER

You can not use $this->getServiceLocator() in controller any more.

You should add one more class IndexControllerFactory where you will get dependencies and inject it in IndexController

First refactor your config:

'controllers' => [
    'factories' => [
        Controller\IndexController::class => Controller\IndexControllerFactory::class,
    ],
],

Than create IndexControllerFactory.php

<?php

namespace ModuleName\Controller;

use ModuleName\Controller\IndexController;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;

class IndexControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container,$requestedName, array $options = null)
    {
        return new IndexController(
            $container->get(\Doctrine\ORM\EntityManager::class)
        );
    }
}

At the end refactor you IndexController to get dependencies

public function __construct(\Doctrine\ORM\EntityManager $object) {
    $this->objectManager = $object;
    $this->trust = new Trust;
}

You should check official documentation zend-servicemanager and play around a little bit...

0
J.Ewa On

Whilst the accepted answer is correct, I will implement mine a bit differently by injecting the container into the controller and then get other dependencies in constructor like so...

<?php

namespace moduleName\Controller\Factory;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use moduleName\Controller\ControllerName;

class ControllerNameFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        return new ControllerName($container);
    }

}

Your controller should look something like this:

namespace ModuleName\Controller;


use Doctrine\ORM\EntityManager;
use Zend\ServiceManager\ServiceManager;


class ControllerName extends \App\Controller\AbstractBaseController
{

    private $orm;

    public function __construct(ServiceManager $container)
    {
        parent::__construct($container);

        $this->orm = $container->get(EntityManager::class);
    }

In your module.config, be sure to register the factory like so:

'controllers' => [
    'factories' => [
        ControllerName::class => Controller\Factory\ControllerNameFactory::class,
],