簡體   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