Php 更改Zend Framework 2默认模板解析器行为

Php 更改Zend Framework 2默认模板解析器行为,php,view,namespaces,zend-framework2,Php,View,Namespaces,Zend Framework2,我刚刚开始研究Zend framework 2。有一件事我似乎不明白,那就是当我不在viewmodel中传递视图模板时,在决定使用哪个视图模板时,如何更改框架的行为 当我自己寻找答案时,我发现以下内容,其中说明Zend使用以下路径解析视图模板: {normalized module name}/{normalized controller name}/{normalized action name} (来源:) 现在,我希望编辑或删除规范化的模块名称段。所有视图文件都保留在“我的模块/视图”文件

我刚刚开始研究Zend framework 2。有一件事我似乎不明白,那就是当我不在viewmodel中传递视图模板时,在决定使用哪个视图模板时,如何更改框架的行为

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

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

(来源:)

现在,我希望编辑或删除规范化的模块名称段。所有视图文件都保留在“我的模块/视图”文件夹中。我想改变这一点的原因是,我使用子名称空间作为我的模块名,导致名称空间的第一段作为规范化模块名(这对我来说不够具体)

为给您一个示例,模块
Foo\Bar
将从以下位置呈现示例视图:

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

我想将该默认行为更改为:


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

视图模型的右模板由
Zend\MVC\view\Http\InjectTemplateListener在MVC事件“dispatch”(中定义)中注入,优先级为-90

您必须创建自定义InjectTemplateListener,并以更高的优先级将其注册到同一事件


但我建议在每个操作中手动设置模板,因为性能问题-请参见

从zf 2.3开始,您可以使用额外的配置参数查看管理器['controller\u map']
来启用不同的模板名称解析

查看此PR了解更多信息:

将导致按照以下规则解析以“Foo\Bar”开头的控制器FQCN:

  • strip\Controller\namespace
  • 类名称中的带尾随控制器
  • 屈折
  • 用斜杠替换名称空间分隔符
  • 例如:
    Foo\Bar\Controller\Baz\TestController
    ->
    Foo/Bar/Baz/test/actionname

    更新:


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

    我遇到了类似的问题,下面是我的解决方案

    默认模板注入器连接到当前控制器的优先级为-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));
        }
    }
    

    下面是我的博客中的链接,我在博客中详细介绍了它:

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


    因此,不要浪费时间寻找一种方法来完成最终将手动完成的工作:D

    为了改进下一个开发人员答案,我在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比使用数组方法快。

    我不确定是否能理解,但这就是我如何设置模板$view->setTemplate('path');嘿@dixromos98,如果您想手动告诉ZF2它需要使用特定视图,那么您建议的答案确实是正确的。我只是好奇在不设置模板的情况下,是否有任何方法可以改变ZF2的行为。谢谢大家回答我的问题!我把有关这个问题的代码留在办公室,所以我会在周一尽快给你回复,把正确的答案标记为已解决。由于提供了代码示例,下一个开发人员的答案目前最适合我。Iku实际上也是这么说的,但因为我对Zend来说还是个新手,所以理解起来有点困难。Iku和Exlord都告诉我应该手动定义模板,以优化性能,这是有道理的。我也喜欢Xerkus的答案,因为它是完成事情的最“干净”的解决方案。由于我没有足够的声誉来投票给你们所有人,我将下一个开发者的答案标记为解决的答案。但感谢大家的参与。
    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));
        }
    }