更改Zend Framework 2的默认模板解析程序行为

时间:2014-10-17 13:25:49

标签: php view namespaces zend-framework2

我刚刚开始研究Zend框架2.我无法弄清楚的一件事是,当我决定使用什么视图模板时,如何更改框架的行为viewmodel。

当我自己找到答案时,我发现了以下内容,其中指出Zend使用以下路径解析视图模板:

{normalized-module-name}/{normalized-controller-name}/{normalized-action-name}

(资料来源:http://zend-framework-community.634137.n4.nabble.com/Question-regarding-template-path-stack-tp4660952p4660959.html

现在我正在寻找编辑或删除normalized-module-name段。所有视图文件都保留在我的module / views文件夹中。我想改变它的原因是因为我使用子命名空间作为我的模块名称,导致命名空间的第一段作为规范化模块名称(对我来说不够具体)。

举个例子,模块Foo\Bar将导致从以下位置呈现示例视图:

/modules/Foo/Bar/view/foo/test/index.phtml

我想将默认行为更改为:

/modules/Foo/Bar/view/bar/test/index.phtml

5 个答案:

答案 0 :(得分:4)

从zf 2.3开始,您可以使用额外的配置参数view_manager['controller_map']来启用不同的模板名称解析。

请查看此PR以获取更多信息:https://github.com/zendframework/zf2/pull/5670

'view_manager' => array(
    'controller_map' => array(
        'Foo\Bar' => true,
    ),
);

将导致控制器FQCN以' Foo \ Bar'开头。按照这些规则解决:

  1. strip \ Controller \ namespace
  2. 在classname中删除控制器
  3. 将CamelCase改为破折号
  4. 用斜杠替换命名空间分隔符
  5. 例如:Foo\Bar\Controller\Baz\TestController - > foo/bar/baz/test/actionname

    <强>更新

    从zend-mvc v3.0开始,这是默认行为

答案 1 :(得分:3)

我有类似的问题,这是我的解决方案。

默认模板注入器以优先级-90附加到当前控制器的事件管理器,仅当视图模型未提供模板名称时才会解析模板名称。 知道了这一点,您可以使用所需的逻辑创建自己的模板注入器,并将其附加到具有更高优先级的事件管理器。

请参阅以下代码:

public function onBootstrap(EventInterface $event)
{
    $eventManager = $event->getApplication()->getEventManager();

    $eventManager->getSharedManager()
        ->attach(
            'Zend\Stdlib\DispatchableInterface',
            MvcEvent::EVENT_DISPATCH,
            new TemplateInjector(),
            -80 // you can put here any negative number higher -90
        );
}

您的模板注入器,它解析模板路径而不是默认路径。

class TemplateInjector 
{
    public function __invoke(MvcEvent $event)
    {
        $model = $event->getResult();

        if (!$model instanceof ViewModel)
        {
            return;
        }

        $controller = $event->getTarget();


        if ($model->getTemplate())
        {
            return ;
        }

        if (!is_object($controller))
        {
            return;
        }

        $namespace = explode('\\', ltrim(get_class($controller), '\\'));

        $controllerClass = array_pop($namespace);
        array_pop($namespace); //taking out the folder with controllers
        array_shift($namespace); //taking out the company namespace

        $moduleName = implode('/', $namespace);

        $controller = substr($controllerClass, 0, strlen($controllerClass) - strlen('Controller'));
        $action = $event->getRouteMatch()->getParam('action');
        $model->setTemplate(strtolower($moduleName.'/'.$controller.'/'.$action));
    }
}

以下是我的博客中的链接,我在其中详细介绍了它:http://blog.igorvorobiov.com/2014/10/18/creating-a-custom-template-injector-to-deal-with-sub-namespaces-in-zend-framework-2/

答案 2 :(得分:0)

ViewModel的正确模板被注入MVC​​事件&#39; dispatch&#39; (由ViewManager定义)Zend\Mvc\View\Http\InjectTemplateListener,优先级为-90

您必须创建自定义的InjectTemplateListener并以相同事件的更高优先级注册它。​​

但我建议手动设置每个动作的模板,因为性能 - 请参阅http://samminds.com/2012/11/zf2-performance-quicktipp-1-viewmodels/

答案 3 :(得分:0)

模板名称解析是一个繁重的过程(在系统资源上),所有关于ZF2性能的文章都说你应该手动提供模板名称以提高性能。

所以不要浪费时间寻找一种方法来做一些你最终会手动做的事情:D

答案 4 :(得分:0)

为了改进Next Developer的答案,我在TemplateInjector.php中编写了以下代码:

class TemplateInjector
{

    public function __invoke(MvcEvent $event)
    {
        $model = $event->getResult();

        if (!$model instanceof ViewModel) {
            return;
        }

        if ($model->getTemplate()) {
            return;
        }

        $controller = $event->getTarget();

        if (!is_object($controller)) {
            return;
        }

        $splitNamespace = preg_split('/[\\\]+/', ltrim(get_class($controller), '\\'));
        $moduleName = $splitNamespace[1];
        $controller = $splitNamespace[0];
        $action = $event->getRouteMatch()->getParam('action');
        $model->setTemplate(strtolower($moduleName . '/' . $controller . '/' . $action));
    }
}

我改变了构建模板路径的方法。使用regexp比使用数组方法更快。