2013-04-13 6 views
2

Я написал простой помощник вида URL, который расширяет Zend\View\Helper\Url и прикрепили его к ViewHelperManager:Расширение Zend View Helper Url в Zend Framework 2

MyNamespace\View\Helper\Url

namespace MyNamespace\View\Helper; 

use Zend\View\Helper\Url as ZendUrl; 

class Url extends ZendUrl { 

    public function __invoke($name = null, array $params = array(), $options = array(), $reuseMatchedParams = false) { 
     $link = parent::__invoke($name, $params, $options, $reuseMatchedParams); 
     ... 
     return $link; 
    } 

} 

Application\Module

namespace Application; 

use ... 

class Module { 

    public function onBootstrap(MvcEvent $mvcEvent) { 
     $application = $mvcEvent->getApplication(); 
     $serviceManager = $application->getServiceManager(); 
     $viewHelperManager = $serviceManager->get('ViewHelperManager'); 
     $viewHelperManager->setInvokableClass('url', 'MyNamespace\View\Helper\Url'); 
     ... 
    } 

} 

Теперь приложение выдает исключение:

Fatal error: Uncaught exception 'Zend\View\Exception\RuntimeException' with message 'No RouteStackInterface instance provided' in /var/www/foo/bar/vendor/zendframework/zendframework/library/Zend/View/Helper/Url.php on line 76

Zend\View\Exception\RuntimeException: No RouteStackInterface instance provided in /var/www/foo/bar/vendor/zendframework/zendframework/library/Zend/View/Helper/Url.php on line 76

Я отлажена как Url классов. Wenn MyNamespace\View\Helper\Url, метод Zend\View\Helper\Url#setRouter(...) не вызывается и маршрутизатор не установлен. Не поймите почему ...

Как заставить его работать?

+1

Возможно, это поможет: https://github.com/zendframework/zf2/blob/master/library/Zend/Mvc/Service/ViewHelperManagerFactory.php#L63-L78 –

+0

Спасибо! Да, я думаю, это помогает понять проблему. Класс помощника просмотра URL-адресов жестко закодирован ([строка 64] (https://github.com/zendframework/zf2/blob/master/library/Zend/Mvc/Service/ViewHelperManagerFactory.php#L64)). Это означает для меня, что помощник просмотра URL не может быть расширен без перезаписи 'Zend \ Mvc \ Service \ ViewHelperManagerFactory # createService (...)'. Правильно? – automatix

+0

Ну, вы можете просто создать свою собственную фабрику и ввести компоненты. –

ответ

1

Не проверял это, так что я не знаю, если это работает, я просто угадать:

Заменить:

$viewHelperManager->setInvokableClass('url', 'MyNamespace\View\Helper\Url'); 

с:

$viewHelperManager->setFactory('url', function ($sm) use($serviceLocator) { 
    $helper = new \MyNamespace\View\Helper\Url; 
    $router = Console::isConsole() ? 'HttpRouter' : 'Router'; 
    $helper->setRouter($serviceLocator->get($router)); 

    $match = $serviceLocator->get('application') 
    ->getMvcEvent() 
    ->getRouteMatch(); 

    if ($match instanceof RouteMatch) { 
     $helper->setRouteMatch($match); 
    } 

    return $helper; 
}); 
0

решение Айдын работал на я, я поставил код, более или менее нетронутый в getViewHelperConfig модуля. php

public function getViewHelperConfig() 
{ 
    return array(
     'invokables' => array(
      ..... 
     ), 
     'factories' => array(
      'modalurl'   => function ($helperPluginManager) { 
       $serviceLocator = $helperPluginManager->getServiceLocator(); 
       $view_helper = new \Application\View\Helper\ModalUrl(); 
       $router = \Zend\Console\Console::isConsole() ? 'HttpRouter' : 'Router'; 
       $view_helper->setRouter($serviceLocator->get($router)); 

       $match = $serviceLocator->get('application') 
        ->getMvcEvent() 
        ->getRouteMatch(); 

       if ($match instanceof RouteMatch) { 
        $view_helper->setRouteMatch($match); 
       } 

       return $view_helper; 
      } 
     ), 
    ); 
} 
1

Вы также можете использовать инициализаторы!

'view_helpers' => array(
    'invokables' => array(
     'MyUrl' => 'MyModule\View\Helper\MyUrl' 
    ), 
    'initializers' => array(
     function ($instance, $sm) { 
      if ($instance instanceof \Zend\View\Helper\Url) { 
       $serviceLocator = $sm->getServiceLocator(); 

       $router = \Zend\Console\Console::isConsole() ? 'HttpRouter' : 'Router'; 
       $instance->setRouter($serviceLocator->get($router)); 

       $match = $serviceLocator->get('application') 
        ->getMvcEvent() 
        ->getRouteMatch(); 

       if ($match instanceof RouteMatch) { 
        $instance->setRouteMatch($match); 
       } 
      } 
     } 
    ) 
) 

И Вы можете продлить \ Zend \ View \ Helper \ Url, как Вы хотите, чтобы он

namespace MyModule\View\Helper; 

use Zend\View\Helper\Url as ZendUrl; 

class MyUrl extends ZendUrl { 

    public function __invoke() { 
     return parent::__invoke('MyRoute'); 
    } 

} 
0

Хотя этот вопрос довольно старый, полагал, что это может быть стоит добавить переопределение на основе конфигурации и здесь используя завод, зарегистрированный в HelperPluginManager:

module.config.php Внутри:

'view_helpers' => array(
    'factories'=> array(
     'url' => 'Application\View\Helper\UrlFactory', 
    ) 
), 

И вид помощник плагин сам завод:

<?php 

namespace Application\View\Helper; 

use Zend\Console\Console; 
use Zend\Mvc\Router\RouteMatch; 
use Zend\Mvc\Router\RouteStackInterface; 
use Zend\ServiceManager\FactoryInterface; 
use Zend\ServiceManager\ServiceLocatorInterface; 
use Zend\View\Helper\Url as BaseUrlHelper; 
use Zend\View\HelperPluginManager; 

class UrlFactory implements FactoryInterface 
{ 
    /** 
    * Create service 
    * 
    * @param ServiceLocatorInterface $helperPluginManager 
    * @return mixed 
    */ 
    public function createService(ServiceLocatorInterface $helperPluginManager) 
    { 
     /** 
     * @var $helperPluginManager HelperPluginManager 
     * @var $router RouteStackInterface 
     */ 
     $serviceLocator = $helperPluginManager->getServiceLocator(); 
     $helper = new Url(); 

     $router = Console::isConsole() ? 'HttpRouter' : 'Router'; 
     $router = $serviceLocator->get($router); 
     $helper->setRouter($router); 

     $match = $serviceLocator->get('application') 
      ->getMvcEvent() 
      ->getRouteMatch() 
     ; 

     if ($match instanceof RouteMatch) { 
      $helper->setRouteMatch($match); 
     } 

     return $helper; 
    } 
} 

Хитрость здесь действительно является то, что на этом заводе, один получает только локатор HelperPluginManager службы. Чтобы получить доступ к другим службам, сначала нужно получить глобальный локатор службы (который выполняется use в глобальном локаторе службы из-за пределов закрытия во всех других решениях).

Смежные вопросы