Сервис 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()
Другие вопросы по тегам