【问题标题】:How to create a dynamic template chooser in Symfony2?如何在 Symfony2 中创建动态模板选择器?
【发布时间】:2014-08-08 09:46:25
【问题描述】:

我想创建一个动态模板定位器。 基本上,当满足某些全局条件时,我想优先考虑某些捆绑包中的模板。类似于包继承的工作方式,但运行时是动态的。

它应该像这样工作: 我有一些“类别”,每个类别都有自己的捆绑包。当要呈现模板时,我会检查当前设置的类别并在该类别的包中搜索此模板。如果未找到,则回退到内置机制。

我虽然关于覆盖Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator,但这似乎有点骇人听闻。如果可能的话,我想模仿捆绑继承,但我找不到它的实现位置。

你会如何处理这个问题? TemplateLocator 是注入我的逻辑的最佳位置吗?

【问题讨论】:

    标签: php symfony templating


    【解决方案1】:

    这可能不是最漂亮的解决方案,但它就像一个魅力。

    我对@9​​87654321@ 服务进行了子类化和重载:

    class CategoryAwareTemplateLocator extends TemplateLocator
    {
        /**
         * @var string
         */
        protected $categoryBundle = null;
    
        /**
         * @var string
         */
        protected $defaultBundle = null;
    
        /**
         * {@inheritDoc}
         */
        public function __construct(FileLocatorInterface $locator, $cacheDir = null)
        {
            parent::__construct($locator, $cacheDir);
        }
    
        /**
         * {@inheritDoc}
         */
        public function locate($template, $currentPath = null, $first = true)
        {
            if(!$template instanceof TemplateReferenceInterface) {
                throw new \InvalidArgumentException('The template must be an instance of TemplateReferenceInterface.');
            }
    
            $templateParameters = $template->all();
            $templateBundle = array_key_exists('bundle', $templateParameters) ? $templateParameters['bundle'] : null;
    
            if(
                null !== $this->categoryBundle &&
                $templateBundle === $this->defaultBundle /* Override only defaultBundle templates */
            ) {
                /* Try our category bundle first */
                $categoryTemplate = clone $template;
                $categoryTemplate->set('bundle', $this->categoryBundle);
    
                try {
                    return parent::locate($categoryTemplate, $currentPath, $first);
                } catch(\InvalidArgumentException $exception) {
                    /* Just fall through to default mechanism */
                }
            }
    
            return parent::locate($template, $currentPath, $first);
        }
    
        /**
         * @param string $defaultBundle
         * @param string $categoryBundle
         */
        public function setCategoryBundle($defaultBundle, $categoryBundle)
        {
            $this->categoryBundle = $categoryBundle;
            $this->defaultBundle = $defaultBundle;
        }
    }
    

    所需的包名称在运行时通过 setter 注入(在“编译时”不知道)。这也有点丑。

    最棒的是这适用于所有树枝标签(includeuse、...)。唯一的问题是您无法访问要覆盖的“默认”模板。如果您尝试从覆盖它的模板中执行此操作,您将收到嵌套级别(无限递归)错误。

    这不是什么大问题,因为您可以使用组合巧妙地“继承”基本模板(将模板拆分为更小的模板)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      • 2018-04-16
      相关资源
      最近更新 更多