繁体   English   中英

如何在Symfony2中创建动态模板选择器?

[英]How to create a dynamic template chooser in Symfony2?

我想创建一个动态模板定位器。 基本上,当某些全局条件满足时,我想对特定捆绑包中的模板进行优先排序。 与捆绑继承类似,但是运行时动态。

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

我虽然要重写Symfony\\Bundle\\FrameworkBundle\\Templating\\Loader\\TemplateLocator ,但这似乎有点骇人听闻。 如果可能,我想模仿捆绑继承,但是我找不到实现的地方。

您将如何处理? TemplateLocator是插入我的逻辑的最佳位置吗?

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

我继承并重载了TemplateLocator服务:

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 ,...)。 唯一的问题是您无法访问要覆盖的“默认”模板。 如果尝试从覆盖它的模板中执行此操作,则会出现嵌套级别(无限递归)错误。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM