How to inject Zend Service Manager in ZF3 Controllers

Zend Service Manager component is Zend Framework’s implementation of service locator pattern. This object is very usefull component for an application and is largely used in ZF applications.

Unfortunately in ZF3 default application, Service Manager component is no more available in controllers.

An official solution exsists for this, but in this little tutorial, I want to share an easy solution to inject Service Manager in all controllers.

To implement this solution, we will write our controllers by extending an abstract controller class written to handle a Service Manager instance. Then we will start to create controllers by invoking a factory class that inject Zend Service Manager instance into them.

Before start, let’s say that I will assume you just have a working Skeleton ZF3 Application and you just configured your ZF Service Manager.

First of all, we have to implement abstract controller class. This class will essentially have a setter and a getter for Service Manager object.

module/Application/src/Controller/AbstractController.php:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\ServiceManager\ServiceManager;

class AbstractController extends AbstractActionController
{
    /**
     * @var ServiceManager
     */
    protected $serviceManager;

    /**
     * @return ServiceManager
     */
    public function getServiceManager()
    {
        return $this->serviceManager;
    }

    /**
     * @param mixed $serviceManager
     * @return $this
     */
    public function setServiceManager($serviceManager)
    {
        $this->serviceManager = $serviceManager;
        return $this;
    }
}

Now we need a factory class that will inject ServiceManager object in controllers.

module/Application/src/Controller/ControllerFactory.php:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php

namespace Application\Controller;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;

class ControllerFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $service = (null === $options) ? new $requestedName : new $requestedName($options);

        return $service->setServiceManager($container);
    }
}

Now we have all needed elements and we can implement our controller(s) extending AbstractController. Retreive of object from ServiceManager is shown at line 10.

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?php

namespace Application\Controller;

class IndexController extends AbstractController
{

    public function indexAction()
    {
        $dummy = $this->getServiceManager()->get('dummy');

        return new ViewModel();
    }

}

Finally to make everithing work, we have to instantiate controller in a bit different way.

module/Application/config/module.config.php:

1
2
3
4
5
6
7
8
9
'controllers' => [
    'factories' => [
        \Application\Controller\IndexController::class => \Application\Controller\ControllerFactory::class,
    ],
    'aliases' => [
        'Application\Controller\Index' => \Application\Controller\IndexController::class,
    ],

],

See also