ServiceManager in ZF3
Asked Answered
G

2

8

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;
}
Godber answered 10/2, 2017 at 21:1 Comment(0)
D
15

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...

Doorn answered 11/2, 2017 at 13:2 Comment(3)
Thank you! It's the config where I'd been making a mistake.Godber
Nice example! Considering that you have more than one action per controller, but you have one factory per controller. If you use an object on specific action that dont use on other, you're initializing extra objects on same cases. What should be the solution on this case?Whitcomb
Simple :) create only one action per controller. Actually that is trend now with micro frameworks and PHP middlewares...Doorn
C
0

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,
],
Contra answered 31/1, 2019 at 10:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.