在Zend Framework 2中扩展Zend \ View \ Helper \ Url

时间:2013-04-13 13:03:11

标签: zend-framework2 urlhelper viewhelper

我写了一个简单的网址视图助手,它扩展了Zend\View\Helper\Url并将其附加到ViewHelperManager

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

}

现在应用程序抛出异常:

  

致命错误:在/ var / www / foo / bar / vendor / zendframework / zendframework / library / Zend / View / Helper / Url中显示消息'未提供RouteStackInterface实例'的未捕获异常'Zend \ View \ Exception \ RuntimeException'第76行的.php

     

Zend \ View \ Exception \ RuntimeException:第76行的/var/www/foo/bar/vendor/zendframework/zendframework/library/Zend/View/Helper/Url.php中没有提供RouteStackInterface实例

我调试了两个Url类。使用Wenn MyNamespace\View\Helper\Url,未调用方法Zend\View\Helper\Url#setRouter(...)且未设置路由器。不明白为什么......

如何让它运作?

4 个答案:

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

答案 1 :(得分: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');
    }

}

答案 2 :(得分:0)

Aydin的解决方案对我有用,我把代码或多或少都没有触及到module.php的getViewHelperConfig

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

答案 3 :(得分: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所有其他解决方案中的闭包外部的全局服务定位器完成的。