Сервис Zend Framework 2 в View Helper
Мне нужно написать помощник вида, который получает сервис и что-то с ним делать. Я успешно реализовал помощник вида для доступа к локатору сервиса. Проблема в том, что служба, которую я хочу получить, не обнаруживается через локатор службы при вызове метода __invoke.
Код помощника вида:
<?php
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper,
Zend\ServiceManager\ServiceLocatorAwareInterface,
Application\Model;
class LoggedCustomer extends AbstractHelper implements ServiceLocatorAwareInterface
{
use \Zend\ServiceManager\ServiceLocatorAwareTrait;
public function __invoke()
{
$model = new Model\Customer($this->getServiceLocator());
return $model->getCurrent();
}
}
Фрагмент кода модели:
namespace Application\Model;
use Application\Entity,
Andreatta\Model\Base as Base;
class Customer extends Base
{
/**
*
* @return Zend\Authentication\AuthenticationService
*/
public function getAuthService()
{
$serviceLocator = $this->getServiceLocator();
return $serviceLocator->get('Application\Auth');
}
/**
*
* @return Zend\Authentication\Adapter\AdapterInterface
*/
protected function getAuthAdapter()
{
return $this->getAuthService()->getAdapter();
}
public function getCurrent()
{
$authService = $this->getAuthService();
if ($authService->hasIdentity())
return $authService->getIdentity();
return null;
}
Фрагмент из module.config.php:
'service_manager' => array
(
'factories' => array
(
'Application\Auth' => function($sm)
{
$authService = $sm->get('doctrine.authenticationservice.application');
$authService->setStorage( new \Zend\Authentication\Storage\Session('Application\Auth'));
return $authService;
},
),
),
'view_helpers' => array
(
'invokables' => array
(
'loggedCustomer' => 'Application\View\Helper\LoggedCustomer',
),
),
При вызове помощника вида из любого представления я получаю следующее:
Zend\View\HelperPluginManager::get was unable to fetch or create an instance for Application\Auth
Странно то, что приложение работает правильно (то есть этот сервис обычно используется другими частями приложения).
РЕДАКТИРОВАТЬ:
Я провел некоторое исследование и думаю, что единственные сервисы, к которым я могу получить доступ через диспетчер сервисов внутри помощника вида, это те, которые зарегистрированы в разделе 'view_manager' файла module.config.php. У кого-нибудь есть идеи, как получить доступ к другим сервисам?
5 ответов
$this->getServiceLocator()
в помощнике по видению могут получить только другие помощники по видам, которые вам нужны $this->getServiceLocator()->getServiceLocator()
чтобы получить услуги приложения
@rafaame: я нахожу простой способ получить доступ к сервисному локатору в представлении Helper
Мы просто используем:
$this->getView()->getHelperPluginManager()->getServiceLocator();
получить сервисный локатор
namespace Tmcore\View\Helper;
use Zend\View\Helper\AbstractHelper;
class Resource extends AbstractHelper
{
public function adminResource()
{
$sm = $this->getView()->getHelperPluginManager()->getServiceLocator();
$adminConfig = $sm->get('ModuleManager')->loadModule('admin')->getConfig();
return $adminConfig;
}
}
Я полагаю, вы получаете Zend\View\HelperPluginManager
вместо правильного ServiceManager
, Вероятно, вы вводите его не так, как следует.
Это имеет смысл, если это ваш полный LoggedCustomer
код, так как вы не сохраняете СМ. Насколько я знаю, если вы реализуете ServiceLocatorAwareInterface, SM будет введен, но вы должны справиться с этим.
ОБНОВИТЬ:
извините, я не осознавал, что у вас был ServiceLocatorAwareTrait; это то же самое.
Но, читая http://framework.zend.com/manual/2.0/en/modules/zend.service-manager.quick-start.html я вижу
По умолчанию Zend Framework MVC регистрирует инициализатор, который внедрит экземпляр ServiceManager, который является реализацией Zend\ServiceManager\ServiceLocatorInterface, в любой класс, реализующий Zend\ServiceManager\ServiceLocatorAwareInterface. Простая реализация выглядит следующим образом.
Таким образом, диспетчер служб вводится только... если вы реализуете ServiceLocatorAwareInterface в контроллере.
Итак, вы должны вручную ввести сервис-менеджер.
для этого я использую для создания фабрики в Module.php вместо создания invokable в конфигурации. для этого вы реализуете эту функцию:
public function getViewHelperConfig()
{
return array(
'factories' => array(
'loggedCustomer' => function($sm) {
$vh = new View\Helper\LoggedCustomer();
$vh->setServiceLocator($sm->getServiceLocator());
return $vh;
}
);
}
Кроме того, у меня не будет помощника вида, реализующего ServiceLocatorAwareInterface, так что ничего больше не вводится автоматически.
И с этим будет работать
Похоже, что менеджер сервисов, который вводится в помощник вида, имеет только сервисы, которые зарегистрированы в разделе 'view_manager' конфигураций модуля.
Можно внедрить "главный" диспетчер сервисов, зарегистрировав помощник вида как фабрику следующим образом:
'view_helpers' =>
[
'factories' =>
[
'loggedCustomer' => function($pluginManager)
{
$serviceLocator = $pluginManager->getServiceLocator();
$viewHelper = new View\Helper\LoggedCustomer();
$viewHelper->setServiceLocator($serviceLocator);
return $viewHelper;
},
]
],
Но вы должны убедиться, что вы обрабатываете это в методе setServiceLocator в помощнике вида. В противном случае "ограниченный" менеджер сервисов будет добавлен в помощник вида позже. Как это:
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
if($this->serviceLocator !== null)
return $this;
$this->serviceLocator = $serviceLocator;
return $this;
}
Это решает проблему, но мне кажется, что это огромный взлом.
По мнению помощников, если вы хотите получить доступ к службам приложений, используйте
$this->getServiceLocator()->getServiceLocator()