【问题标题】:Change Zend Framework 2 default template resolver behavior更改 Zend Framework 2 默认模板解析器行为
【发布时间】:2014-12-13 02:22:24
【问题描述】:

我刚刚开始研究 Zend 框架 2。我似乎无法弄清楚的一件事是如何在框架决定使用什么视图模板时更改框架的行为,而我没有传入它视图模型。

当我自己寻找答案时,我发现了以下内容,这表明 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

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

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

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

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

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

【问题讨论】:

  • 不确定我明白了,但这就是我设置模板的方式 $view->setTemplate('path');
  • 嘿@dixromos98,如果您想手动告诉 ZF2 它需要使用特定视图,您建议的答案确实是正确的。我只是好奇是否有什么方法可以在不设置模板时改变 ZF2 的行为。
  • 谢谢大家回答我的问题!我把这个问题的代码留在了办公室,所以我会在星期一尽快回复你,将正确答案标记为已解决。

标签: php view namespaces zend-framework2


【解决方案1】:

为了改进 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));
    }
}

我改变了构建模板路径的方式。使用正则表达式比使用数组方法更快。

【讨论】:

    【解决方案2】:

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

    查看此 PR 了解更多信息:https://github.com/zendframework/zf2/pull/5670

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

    将导致以 'Foo\Bar' 开头的控制器 FQCN 按照这些规则进行解析:

    1. 剥离 \Controller\ 命名空间
    2. 去除类名中的尾随控制器
    3. 使用 CamelCase 来破折号
    4. 用斜杠替换命名空间分隔符

    例如:Foo\Bar\Controller\Baz\TestController -> foo/bar/baz/test/actionname

    更新:

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

    【讨论】:

      【解决方案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/

      【讨论】:

      • Next Developer 的回答是目前最适合我的,因为提供了代码示例。 Iku 实际上也是这么说的,但由于我对 Zend 还很陌生,所以有点难以理解。 Iku 和 Exlord 都告诉我应该手动定义模板,优化性能,这两者都有道理。我也喜欢 Xerkus 的回答,因为它是完成工作的最“干净”的解决方案。由于我没有足够的声誉来支持你们所有人,因此我将 Next Developer 的答案标记为已解决的答案。不过谢谢大家的参与。
      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        ViewModel 的正确模板由 Zend\Mvc\View\Http\InjectTemplateListener 以 -90 的优先级注入到 MVC 事件“调度”(在 ViewManager 中定义)中

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

        但出于性能考虑,我建议在每个操作中手动设置模板 - 请参阅 http://samminds.com/2012/11/zf2-performance-quicktipp-1-viewmodels/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-09-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多