Magento 上 catalog_category_view 的自定义布局

Custom layouts for catalog_category_view on Magento

我需要能够对不同的类别使用不同的布局,select在类别的 自定义设计 选项卡和 页面布局中编辑 字段。

我正在使用 Magento 1.9.1.0。

在我的 config.xml 我有:

<global>
    <page>
        <layouts>
            <module_home module="page" translate="label">
                <label>Module Home</label>
                <template>page/base.phtml</template>
                <layout_handle>module_home</layout_handle>
            </module_home>

            <module_categories module="page" translate="label">
                <label>Module Categories</label>
                <template>page/base.phtml</template>
                <layout_handle>module_categories</layout_handle>
            </module_categories>
        </layouts>
    </page>
    ...

在我的 layouts.xml 文件中我有:

<default>
    <reference name="root">...</reference>
</default>
<module_home translate="label">...</module_home>
<module_categories translate="label">...</module_categories>

当我从类别管理员 select 模块类别 布局时,我没有得到 module_categories[ 的更改=36=] 处理程序,仅在 <default>.

上设置的处理程序

如果我这样强制:

<catalog_category_view>
    <update handle="module_categories" />
</catalog_category_view>

我确实得到了更改,但我想要多个处理程序,select在管理员上编辑为布局。

也许我做错了什么?找不到如何执行此操作的示例,也许您可​​以指出某个地方?谢谢!

您对 <update /> 指令的想法是正确的。只需将它放在管理员的类别 Custom Layout Update 字段中,该类别就会应用该布局句柄。您仍然可以使用 Page Layout 字段设置页面模板。

您需要使用 <update /> 指令显式指定布局句柄的原因是因为 Magento 的类别控制器不使用 layout_handle 节点,而 Magento 的其他部分,如 Magento 的 CMS 页面控制器, 请使用它。

例如,让我们看一下Mage_Cms_PageController,它负责渲染一个CMS页面:

public function viewAction()
{
    $pageId = $this->getRequest()
        ->getParam('page_id', $this->getRequest()->getParam('id', false));
    if (!Mage::helper('cms/page')->renderPage($this, $pageId)) {
        $this->_forward('noRoute');
    }
}

让我们深入研究一下 Mage_Cms_Helper_Page::renderPage(),它调用 Mage_Cms_Helper_Page::_renderPage():

protected function _renderPage(Mage_Core_Controller_Varien_Action  $action, $pageId = null, $renderLayout = true)
{

    $page = Mage::getSingleton('cms/page');

    /* ... */

    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());
    }

    /* ... */
}

我们在这里看到两个重要的逻辑。

首先,_renderPage() 调用 $action->getLayout()->helper('page/layout')->applyHandle($handle)。如果深入挖掘,您会发现 Mage_Page_Helper_Layout::applyHandle() 负责应用配置 XML:

定义的适当 layout_handle
public function applyHandle($pageLayout)
{
    $pageLayout = $this->_getConfig()->getPageLayout($pageLayout);

    if (!$pageLayout) {
        return $this;
    }

    $this->getLayout()
        ->getUpdate()
        ->addHandle($pageLayout->getLayoutHandle());

    return $this;
}

其次,_renderPage() 调用 $action->getLayout()->helper('page/layout')->applyTemplate($page->getRootTemplate())。类似于 applyHandle()applyTemplate() 应用实际页面模板。

因此,这解释了为什么在 CMS 页面中您可以依赖配置 XML 中定义的 layout_handle。现在,让我们找出为什么它对类别不可靠。

我们来看Mage_Catalog_CategoryController::viewAction(),它负责展示一个分类页面:

public function viewAction()
{
    if ($category = $this->_initCatagory()) {
        $design = Mage::getSingleton('catalog/design');
        $settings = $design->getDesignSettings($category);

        /* ... */

        // apply custom layout update once layout is loaded
        if ($layoutUpdates = $settings->getLayoutUpdates()) {
            if (is_array($layoutUpdates)) {
                foreach($layoutUpdates as $layoutUpdate) {
                    $update->addUpdate($layoutUpdate);
                }
            }
        }

        /* ... */

        // apply custom layout (page) template once the blocks are generated
        if ($settings->getPageLayout()) {
            $this->getLayout()->helper('page/layout')->applyTemplate($settings->getPageLayout());
        }

        /* ... */
    }
    elseif (!$this->getResponse()->isRedirect()) {
        $this->_forward('noRoute');
    }
}

剥离所有默认布局逻辑,我们剩下两部分:

        // apply custom layout update once layout is loaded
        if ($layoutUpdates = $settings->getLayoutUpdates()) {
            if (is_array($layoutUpdates)) {
                foreach($layoutUpdates as $layoutUpdate) {
                    $update->addUpdate($layoutUpdate);
                }
            }
        }

这将通过类别的布局更新(如管理中 Custom Layout Update 字段中的定义)并应用它们。这就是为什么使用 <update handle="some_handle" /> 有效。

还有...

        // apply custom layout (page) template once the blocks are generated
        if ($settings->getPageLayout()) {
            $this->getLayout()->helper('page/layout')->applyTemplate($settings->getPageLayout());
        }

这将应用自定义页面模板,类似于 CMS 页面逻辑的做法,使用 Mage_Page_Helper_Layout::applyTemplate()

现在,注意到缺少什么了吗?

是的,类别控制器不会调用 Mage_Page_Helper_Layout::applyHandle() 来应用配置 XML 中定义的 layout_handle。这意味着您可以使用 Page Layout 字段为该类别指定一个特定的页面模板,但是不会应用模板附带的 layout_update

希望这能澄清为什么您的 layout_update 节点没有按照您期望的方式在类别页面上使用。 Magento 充满了像这样的奇怪行为和不一致:)