布局更新的CMS XML句柄


13

我曾尝试使用cms句柄来更新cms页面的布局。例如,我试图使用cms_index_index句柄引用root并设置页面模板。这失败了,我不得不通过管理系统直接在主页cms页面显示设置上进行此布局更新。

我还尝试使用cms_page句柄添加一个要引用的块。再次失败了,我不得不通过管理系统来实现布局更新。

我了解到您无法为cms页面分配根模板。正确吗,有人可以解释为什么吗?

我也想知道是否有一种方法可以使cms句柄使用标准引用,例如left,right,root等?我似乎能够引用诸如标题和内容之类的东西。

Answers:


20

为什么更改根模板不起作用

Mage_Cms_IndexController::indexAction()

Mage_Cms_IndexController::viewAction()

负责显示默认主页和CMS页面的页面分别调用帮助程序:

Mage::helper('cms/page')->renderPage($this, $pageId)

如果您跳入帮助程序(位于app / code / core / Mage / Cms / Helper / Page.php)并遵循renderPage()受保护的方法,_renderPage()您将看到Magento两次检查根模板(Magento CE 1.7。 0.2):

if ($page->getRootTemplate()) {
    $handle = ($page->getCustomRootTemplate()
                && $page->getCustomRootTemplate() != 'empty'
                && $inRange) ? $page->getCustomRootTemplate() : $page->getRootTemplate();
    $action->getLayout()->helper('page/layout')->applyHandle($handle);     
}

if ($page->getRootTemplate()) {
    $action->getLayout()->helper('page/layout')
        ->applyTemplate($page->getRootTemplate());
}

这两个调用都在处理了诸如“ cms_page”之类的布局句柄之后发生,因此您在这里很不走运。

您可以做什么来更改根模板

cms_page_render您可以使用一个事件在CMS页面上添加自己的XML布局句柄。创建您自己的扩展程序(我将在此处保留一些详细信息)并在您的中配置事件观察器config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Emzee_Cms>
            <version>0.0.1</version>
        </Emzee_Cms>
    </modules>

    <global>
        <events>
            <cms_page_render>
                <observers>
                    <emzee_cms_page_render>
                        <class>emzee_cms/observer</class>
                        <method>cms_page_render</method>
                    </emzee_cms_page_render>
                </observers>
            </cms_page_render>
        </events>
        <models>
            <emzee_cms>
                <class>Emzee_Cms_Model</class>
            </emzee_cms>
        </models>
    </global>
</config>

添加事件观察者:

<?php

class Emzee_Cms_Model_Observer
{
    public function cms_page_render(Varien_Event_Observer $observer)
    {
        $action = $observer->getEvent()->getControllerAction();

        $actionName = strtolower($action->getFullActionName());
        $action->getLayout()->getUpdate()
            ->addHandle($actionName . '_after');
        return $this;
    }
}

最后,添加新的布局XML句柄(例如在中local.xml):

<?xml version="1.0"?>
<layout version="0.1.0">
    <cms_index_index_after>
        <reference name="root">
            <action method="setTemplate"><template>page/1column.phtml</template></action>
        </reference>
    </cms_index_index_after>
</layout>

您也可以使用此方法来添加一个cms_page_view_after句柄,或在cms_page_render$page对象传递给观察者时创建页面特定的句柄。

为什么您不能在“参考左侧”添加块

您确定所使用的模板有左列吗?这个问题听起来很愚蠢,但是例如默认的“带有右栏的2列”布局仅提供了“内容”和“正确”区域。我可以将块添加到正确的列使用cms_page而不会出现问题,所以这可能是问题所在。

通常,您只能轻松地将块添加到引用中,并在以下情况下回显它们:

  • 所选的根模板使用您正在引用的块(请参阅参考资料app/design/frontend/base/default/template/page/*.phtml),然后
  • 您所引用的块的类型为core/text_list$this->getChildhtml()不带参数的调用,或者执行其他操作以回显所有子块。

没有更多详细信息,我无法告诉您为什么在左侧或右侧列中未回显您的块。


嗨,Matthias。感谢添加事件观察器的建议,我将与我们的一位开发人员一起看看,看看是否能解决问题。这可能是答案!@Alan也提出了类似的观点,即为cms页面设置了正确的默认模板,并且覆盖了句柄。还要感谢您提供的信息,我想现在已经解决了。
马克·韦斯顿

你好 测试了它,它起作用了。还针对页面特定的句柄对其进行了测试,并且可以正常工作,但这并不是最好的解决方案,因为我需要一个不会更改的页面标识符。作为测试,我使用了页面标识符。$cmsPageId = '_' . str_replace('-', '_', $observer->getEvent()->getPage()->getIdentifier()); 如果有人更改了cms页面的URL,则该句柄将不会起作用。理想情况下,管理系统中的CMS页面上将存在“页面密钥”字段,然后可以更改页面url,名称等,并且密钥可以保持不变。
马克·韦斯顿

14

关于“无法使用<reference name="left/> 添加块,是否确定CMS页面上有一个名为left的块?例如,如果您考虑Magento示例数据附带的默认主页,它似乎有一个名为剩下。

那是左栏吗?

但是,如果您查看后端中的页面,则可以看到它已设置为使用根模板

`2 columns with right bar`    

然后在其内容区域中,使用HTML标记添加左列(将所见即所得切换为源视图)

<div class="col-left side-col">
<p class="home-callout"><a href="{{store direct_url="apparel/shoes/womens/anashria-womens-premier-leather-sandal.html"}}"><img src="{{skin url='images/ph_callout_left_top.gif'}}" alt="" border="0" /></a></p>
<p class="home-callout"><img src="{{skin url='images/ph_callout_left_rebel.jpg'}}" alt="" border="0" /></p>
{{block type="tag/popular" template="tag/popular.phtml"}}</div>

这个有向图使您清楚地知道没有块left可以挂接到(单击以查看大图

使用Commerce Bug生成的有向图

关于设置模板,如果您查看“布局”下拉列表的来源

<select id="page_root_template" name="root_template" class=" required-entry select">
    <option value="empty">Empty</option>
    <option value="one_column">1 column</option>
    <option value="two_columns_left">2 columns with left bar</option>
    <option value="two_columns_right" selected="selected">2 columns with right bar</option>
    <option value="three_columns">3 columns</option>
</select>

当你设置此字段中可以看到,得到保存的实际值是一样的东西one_columntwo_columns_left等等,这些值corespond同名的布局句柄。

#File: app/design/frontend/default/modern/layout/page.xml
<page_one_column translate="label">
    <label>All One-Column Layout Pages</label>
    <reference name="root">
        <action method="setTemplate"><template>page/1column.phtml</template></action>
        <!-- Mark root page block that template is applied -->
        <action method="setIsHandle"><applied>1</applied></action>
        <action method="setLayoutCode"><name>one_column</name></action>
    </reference>
</page_one_column>
...
<page_two_columns_left translate="label">
    <label>All Two-Column Layout Pages (Left Column)</label>
    <reference name="root">
        <action method="setTemplate"><template>page/2columns-left.phtml</template></action>
        <!-- Mark root page block that template is applied -->
        <action method="setIsHandle"><applied>1</applied></action>
        <action method="setLayoutCode"><name>two_columns_left</name></action>
    </reference>
</page_two_columns_left>

Magento渲染CMS页面时,它引用保存的值,并向页面添加适当的布局句柄。与问题相切时,在此处添加了该句柄

#File: app/code/core/Mage/Cms/Helper/Page.php
protected function _renderPage(Mage_Core_Controller_Varien_Action  $action, $pageId = null, $renderLayout = true)
{
    //...
    $action->addActionLayoutHandles();        
    if ($page->getRootTemplate()) {
        $handle = ($page->getCustomRootTemplate()
                    && $page->getCustomRootTemplate() != 'empty'
                    && $inRange) ? $page->getCustomRootTemplate() : $page->getRootTemplate();
        $action->getLayout()->helper('page/layout')->applyHandle($handle);
    }  
    //...
}

更重要的是布局句柄的添加顺序

Commerce Bug的处理选项卡

如您在上面的屏幕截图中所见,该page_two_columns_right句柄被添加cms_index_index句柄之后。这意味着,如果您添加布局xml更新代码以更改代码中的模板,则该模板cms_index_index将运行,但是其中的布局更新xml代码page_two_columns_right将在其后运行。

我一直怀疑这是设计使然,以确保在用户界面中设置的模板始终正确。在以前版本的Magento中<action method="setIsHandle"><applied>1</applied></action>,由于相同的原因,似乎存在方法调用。

因此,没有办法使用纯布局xml代码执行您想要的操作。如果您对创建自定义模块和观察者代码感到满意,请调查该cms_page_render事件。这会在loadLayoutUpdates调用之前立即触发,并使您可以在其中滑入其他句柄名称,或删除现有的句柄名称。


感谢Alan,您关于在cms页中添加块的评论完全有意义。我通常使用Magento提供的各种xml句柄为不同的页面设置模板。我对cms页的了解略好一些,这更清楚了为什么我在使用cms页的引用时遇到问题。我需要确保page.xml中的默认句柄具有适用于cms页面的正确布局。似乎我已经忽略了该句柄,因为我通常在其他地方都忽略了它。那是对的吗?请问您是如何生成图形的,以及使用哪种工具查看特定请求的句柄?
马克·韦斯顿

2
@MarkWeston图表和UI均来自Commerce Bug,这是我创建和销售的商业调试工具。(有关详细信息,请参阅alanstorm.com/find_magento_block_name)我不确定我是否了解您关于手柄的问题,但是如果您在default手柄中设置模板,则在管理员中设置的布局仍将获胜(即page_two_columns_right仍将运行)后来)。另外,关于Re:术语-您不会覆盖句柄,您的句柄始终与其他句柄共存-只是它们运行的​​顺序会影响最终结果。
艾伦·斯托姆

欢呼艾伦。我明白了您所谓的使用句柄来设置模板而不是覆盖的意思-好点。感谢您提供有关Commerce Bug的信息。
马克·韦斯顿
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.