Magento上catalog_category_view的自定义布局 [英] Custom layouts for catalog_category_view on Magento

查看:73
本文介绍了Magento上catalog_category_view的自定义布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要能够对不同类别使用不同的布局,这些布局是在类别的自定义设计选项卡和页面布局字段中选择的.

我正在使用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>

当我从类别的管理员选择模块类别布局时,我没有得到 module_categories 处理程序的更改,只有在<default>上设置的更改. /p>

如果我这样强迫它:

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

我确实得到了更改,但是我希望有多个处理程序被选择为管理员上的布局".

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

解决方案

使用<update />指令,您已经有了正确的主意.只需将其放在管理员的类别的Custom Layout Update字段中,该类别应应用该布局句柄.您仍然可以使用Page Layout字段设置页面模板.

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

例如,让我们看一下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);
                }
            }
        }

这将遍历类别的布局更新(在admin的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充满了奇怪的行为和类似的矛盾:)

I need to be able to use different layouts for different categories, selected on the Custom Design tab on the category and Page Layout field.

I'm using Magento 1.9.1.0.

In my config.xml I have:

<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>
    ...

And in my layouts.xml file I have:

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

When I select Module Categories layout from the admin of the category I don't get the changes for module_categories handler, only the ones set on <default>.

If I force it like this:

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

I do get the changes, but I want multiple handlers, selected as Layouts on the admin.

Maybe I'm doing something wrong? Could not find an example for how to do this, maybe you can point somewhere? Thanks!

解决方案

You've got the right idea with the <update /> directive. Just put it in your category's Custom Layout Update field in the admin, and that category should apply that layout handle. You can still set the page template with the Page Layout field.

The reason you need to explicitly specify the layout handle with the <update /> directive is because Magento's category controller does not use the layout_handle node, whereas other parts of Magento, like Magento's CMS page controller, do use it.

For example, let's look at Mage_Cms_PageController, which is responsible for rendering a CMS page:

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

Let's dig deeper and look at Mage_Cms_Helper_Page::renderPage(), which calls 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());
    }

    /* ... */
}

We see two important pieces of logic here.

First, _renderPage() calls $action->getLayout()->helper('page/layout')->applyHandle($handle). If you dig even deeper, you'll see that Mage_Page_Helper_Layout::applyHandle() is responsible for applying the appropriate layout_handle as defined by the configuration XML:

public function applyHandle($pageLayout)
{
    $pageLayout = $this->_getConfig()->getPageLayout($pageLayout);

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

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

    return $this;
}

Second, _renderPage() calls $action->getLayout()->helper('page/layout')->applyTemplate($page->getRootTemplate()). Similar to applyHandle(), applyTemplate() applies the actual page template.

So, this explains why you can depend on the layout_handle as defined in the configuration XML when it comes to CMS pages. Now, let's find out why it's not dependable for categories.

Let's look at Mage_Catalog_CategoryController::viewAction(), which is responsible for displaying a category page:

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

Stripping out all of the default layout logic, we're left with two pieces:

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

This goes through the category's layout updates (as defined in the Custom Layout Update field in the admin) and applies them. This is why using <update handle="some_handle" /> works.

And...

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

This applies the custom page template, similar to how the CMS page logic did it, using Mage_Page_Helper_Layout::applyTemplate().

Now, notice something missing?

Yup, the category controller does not call Mage_Page_Helper_Layout::applyHandle() to apply the layout_handle as defined in the configuration XML. This means that you can use the Page Layout field to give the category a particular page template, but your layout_update that accompanies the template won't get applied!

Hope this clears up why your layout_update node isn't getting used on the category page the way you would expect it to. Magento is full of odd behavior and inconsistencies like this :)

这篇关于Magento上catalog_category_view的自定义布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆