ZF2 контроллер фабрики serviceLocator

Я пытаюсь внедрить диспетчер служб в контроллер.

Фактическая ошибка:

\ Поставщика \ ZendFramework \ Зенд-ServiceManager \ SRC \ Exception \ ServiceLocatorUsageException.php: 34

Служба «Project \ Service \ ProjectServiceInterface» была запрошена для менеджера плагинов типа «Zend \ Mvc \ Controller \ ControllerManager», но не может быть получена.
Предыдущее исключение типа «Zend \ ServiceManager \ Exception \ ServiceNotFoundException» возникло в процессе.
Кстати, служба с именем «Project \ Service \ ProjectServiceInterface» была найдена в родительском локаторе службы «Zend \ ServiceManager \ ServiceManager»: вы забыли использовать $ parentLocator = $ serviceLocator-> getServiceLocator () на своей фабрике код?

Процесс идет:

class BaseController extends AbstractActionController implements ServiceLocatorAwareInterface
{

public function __construct(\Zend\ServiceManager\ServiceLocatorInterface $sl)
{
$this->serviceLocator = $sl;
}
}
  1. Создать контроллер и использовать метод конструктора
  2. Расширить это BaseController в AdminController
  3. Настройка маршрутов до AdminController => /admin
  4. использование Module.php

    public function getControllerConfig()

  5. Используйте ближе как фабрика для создания объекта контроллера, внедряющего serviceLocator

    ‘Project \ Controller \ Project’ => функция ($ sm) {
    $ serviceLocator = $ sm-> getServiceLocator ();
    return new \ Project \ Controller \ ProjectController ($ serviceLocator);
    },

  6. попробуй использовать $this->getServiceLocator()->get('service_name')
  7. Исключение для пропущенного сервиса …..

Теперь проблема заключается в следующем:

/**
*
* @param ServiceLocatorInterface $sl
*/
public function __construct(\Zend\ServiceManager\ServiceLocatorInterface $sl)
{
$rtn = $sl->has('Project\Service\ProjectServiceInterface');
echo '<br />in Constructor: '.__FILE__;var_dump($rtn);
$this->serviceLocator = $sl;
}
public function getServiceLocator()
{
$rtn = $this->serviceLocator->has('Project\Service\ProjectServiceInterface');
echo '<br />in getServiceLocator: '.__FILE__;var_dump($rtn);
return $this->serviceLocator;
}

В пределах __конструктор() сервис НАЙДЕН. В пределах getServiceLocator () метод службы с тем же именем НЕ НАЙДЕН….

в конструкторе: Project \ Controller \ BaseController.php
BOOL (истина)
в getServiceLocator: Project \ Controller \ BaseController.php
BOOL (ложь)

Я что-то пропустил? SharedServiceManager что-то делает здесь?

Вся цель этого упражнения была связана с этим сообщением:

Устаревший: ServiceLocatorAwareInterface устарел и будет удален в версии 3.0 вместе с ServiceLocatorAwareInitializer. …

1

Решение

В Zend Framework 2 есть несколько сервисных локаторов (документы здесь), один общий (в основном используется для ваших собственных служб), один для контроллеров, один для помощников представления, один для валидаторов, … Конкретные также называются менеджеры плагинов.

Сообщение об ошибке, которое вы получаете, просто говорит вам, что вы используете неправильный локатор службы, который извлекает контроллеры, а не общий. Он также предлагает вам, как решить вашу проблему:

Вы забыли использовать $ parentLocator = $ serviceLocator-> getServiceLocator () в вашем заводском коде

Вероятно, происходит (не уверен на 100%), что в конструкторе вы передаете экземпляр общего менеджера сервисов, и с ним все отлично работает. Затем, поскольку контроллер реализует ServiceLocatorAwareInterface, локатор службы контроллера вводится в ваш контроллер, переопределяя тот, который вы определили ранее.

Более того, я думаю, что идея обойдется без решения о ServiceLocatorAwareInterface в версии 3 в том, что вы не внедряете указатель службы в свой контроллер, а вместо этого вводите непосредственно зависимости контроллера.

1

Другие решения

Если вам действительно нужен ServiceLocator, вы должны ввести его с завода
Что-то вроде этого

контроллер:

<?php
namespace Application\Controller;

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

class BaseController extends AbstractActionController
{
protected $serviceLocator = null;

public function __construct(ServiceLocatorInterface $serviceLocator)
{
$this->setServiceLocator($serviceLocator);
}

public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
return $this;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
}

Фабрика:

<?php
namespace Application\Controller\Factory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Application\Controller\BaseController;

class BaseControllerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator);
{
$controller = new BaseController($serviceLocator->getServicelocator());
return $controller;
}
}

?>

в module.config.php

<?php
// ...

'controllers' => [
'factories' => [
'Application\Controller\BaseController' => 'Application\Controller\Factory\BaseControllerFactory',
// ...
],
// ...
2

Вы должны попытаться предотвратить внедрение сервис-менеджера или сервис-локатора в контроллер. Было бы намного лучше ввести фактические зависимости (в вашем случае 'Project\Service\ProjectServiceInterface') прямо в __construct метод вашего класса. Конструктор инъекций (зависимости предоставляются через конструктор класса) считается лучшей практикой в ZF2.

Этот шаблон предотвращает создание экземпляра контроллера без ваших зависимостей (он выдаст ошибку).

Если вы вводите ServiceLocator или же ServiceManager из которого вы будете разрешать фактические зависимости в классе, тогда неясно, что на самом деле нужно классу. Вы можете оказаться в экземпляре класса с отсутствующими зависимостями, которые никогда не должны были создаваться. Вам нужно выполнить пользовательскую проверку внутри класса, чтобы увидеть, доступна ли фактическая зависимость, и выдать ошибку, если она отсутствует. Вы можете предотвратить написание всего этого пользовательского кода, используя шаблон зависимости конструктора.

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

Узнайте больше о том, как внедрить ваши зависимости в моем ответе на похожий вопрос.

ОБНОВИТЬ

О проблеме, с которой вы столкнулись. Классы контроллера реализуют ServiceLocatorAwareInterface и во время строительства ваших контроллеров классов ControllerManager вводит ServiceLocator внутри класса. Бывает здесь, в injectServiceLocator метод в строке 208 в ControllerManager.php. Как @marcosh уже упоминал в своем ответе, это может быть другой локатор службы, чем вы вводили. В этом injectServiceLocator Кроме того, вы также найдете уведомление об устаревании, которое вы упомянули в своем вопросе.

Ваш доступен в __construct метод, потому что в это время (сразу после создания класса) переменная еще не перезаписывается. Позже, когда вы попытаетесь получить к нему доступ в своем getServiceLocator Метод перезаписан.

1
По вопросам рекламы [email protected]