ServiceManager в ZF3

Я знаю, что это широко освещалось в других потоках, но я изо всех сил пытаюсь выяснить, как повторить эффект $this->getServiceLocator() из контроллеров ZF2 в контроллеры ZF3.

Я попытался создать фабрику, используя различные другие ответы и учебные пособия, которые я нашел здесь и в других местах, но в итоге я запутался в каждом из них, поэтому я вставляю свой код, как это было, когда я начинал в надежде, что кто-то может указать мне в правильном направлении?

Из /module/Application/config/module.config.php

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

Из /module/Application/src/Controller/IndexController.php

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

1 ответ

Решение

Вы не можете больше использовать $this->getServiceLocator() в контроллере.

Вы должны добавить еще один класс IndexControllerFactory, где вы получите зависимости и внедрите его в IndexController.

Первый рефакторинг вашей конфигурации:

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

Чем создать 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)
        );
    }
}

По окончании рефакторинга у вас IndexController для получения зависимостей

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

Вы должны проверить официальную документацию Zend-ServiceManager и немного поиграться...

Хотя принятый ответ верен, я буду реализовывать мой немного по-другому, вводя контейнер в контроллер, а затем получу другие зависимости в конструкторе, например так...

<?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);
    }

}

Ваш контроллер должен выглядеть примерно так:

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);
    }

В вашем файле module.config обязательно зарегистрируйте фабрику следующим образом:

'controllers' => [
    'factories' => [
        ControllerName::class => Controller\Factory\ControllerNameFactory::class,
],
Другие вопросы по тегам