Magento - 从右向左移动块

时间:2012-03-15 19:29:28

标签: magento layout-xml

不确定为什么这么难。如果我理解正确THIS,我应该能够迅速实现我的目标......但没有快乐。

所以 - 我正在构建我的第一个主题,并且仍然围绕布局......

我专门在Catalog Product View页面上工作,并且正在将此页面从右列布局转换为左列布局。我只是想把块从右边移到左边。

在默认catalog.xml中,定义了product_list_related

     </catalog_product_view> 
     //...

     <reference name="right">
            <block type="catalog/product_list_related" name="catalog.product.related" before="-" template="catalog/product/list/related.phtml"/>
        </reference>
    </catalog_product_view>

在我的local.xml中,我只是想移动这个块:

    <layout>

    // bunch other page directives

   <catalog_product_view>
        <reference name="root">
            <action method="setTemplate"><template>page/2columns-left.phtml</template></action>
        </reference>

        <reference name="right">
            <action method="unsetChild"><name>catalog.product.related</name></action>
        </reference>

        <reference name="left">
            <action method="insert"><blockName>catalog.product.related</blockName></action>

            // note that that "catalog.leftnav" gets inserted as expected
            <block type="catalog/layer_view" name="catalog.leftnav" after="-" template="catalog/layer/view.phtml"/>
        </reference>

    </catalog_product_view>

    </layout>

如上所述 - 插入catalog.leftnav按预期工作,所以我假设其他所有内容都已正确设置。如果我让模板和其他指令保持不变,目标块会按预期呈现,这告诉我块一旦被正确设置并插入就应该呈现...

这让我疯狂......但Magento还有什么新东西。

干杯 -

B []×

UPDATE

因为我无法让local.xml覆盖工作,所以我只是回到修改后的catalog.xml。我是一个相当聪明的人...它让我担心我不能让这个工作(而且无论如何,那个magento都默默地失败了) - 但是我不能再浪费时间来讨论这个愚蠢的问题了。

继续前进。

UPDATE, again. 

花了一些时间,现在,在magento工作,并更熟悉其复杂性。我今天回到了这个问题,因为我需要让我的local.xml正常工作。

我真的不知道自己错了什么,但这套指令终于奏效了。

        <reference name="right">
                <action method="unsetChild">
                    <alias>catalog.product.related</alias>
                </action>
        </reference>

        <reference name="left">
                <action method="insert">
                    <block>catalog.product.related</block>
                </action>
        </reference>

关键点我会留意其他处理此问题的人:

布局xml指令调用magento类中的可用方法。在这种情况下,Page.xmls“Left”块的类型为Mage_Core_Block_Text,它继承自Mage_Core_Block_Abstract,其中包含方法unsetChildinsert

来自Mage_Core_Block_Abstract

/**
     * Unset child block
     *
     * @param  string $alias
     * @return Mage_Core_Block_Abstract
     */
    public function unsetChild($alias)
    {
        if (isset($this->_children[$alias])) {
            unset($this->_children[$alias]);
        }

        if (!empty($this->_sortedChildren)) {
            $key = array_search($alias, $this->_sortedChildren);
            if ($key !== false) {
                unset($this->_sortedChildren[$key]);
            }
        }

        return $this;
    }

  /**
     * Insert child block
     *
     * @param   Mage_Core_Block_Abstract|string $block
     * @param   string $siblingName
     * @param   boolean $after
     * @param   string $alias
     * @return  object $this
     */
    public function insert($block, $siblingName = '', $after = false, $alias = '')
    {
        if (is_string($block)) {
            $block = $this->getLayout()->getBlock($block);
        }
        if (!$block) {
            /*
             * if we don't have block - don't throw exception because
             * block can simply removed using layout method remove
             */
            //Mage::throwException(Mage::helper('core')->__('Invalid block name to set child %s: %s', $alias, $block));
            return $this;
        }
        if ($block->getIsAnonymous()) {
            $this->setChild('', $block);
            $name = $block->getNameInLayout();
        } elseif ('' != $alias) {
            $this->setChild($alias, $block);
            $name = $block->getNameInLayout();
        } else {
            $name = $block->getNameInLayout();
            $this->setChild($name, $block);
        }

        if ($siblingName === '') {
            if ($after) {
                array_push($this->_sortedChildren, $name);
            } else {
                array_unshift($this->_sortedChildren, $name);
            }
        } else {
            $key = array_search($siblingName, $this->_sortedChildren);
            if (false !== $key) {
                if ($after) {
                    $key++;
                }
                array_splice($this->_sortedChildren, $key, 0, $name);
            } else {
                if ($after) {
                    array_push($this->_sortedChildren, $name);
                } else {
                    array_unshift($this->_sortedChildren, $name);
                }
            }

            $this->_sortInstructions[$name] = array($siblingName, (bool)$after, false !== $key);
        }

        return $this;
    }

本地xml参数很重要,然后,不是名称(特定),而是按顺序:

<reference name="left">
                <action method="insert">
                    <block>catalog.product.related</block>
                    <siblingName>catalog.leftnav</siblingName>
                    <after>1</after>
                    <alias>catalog_product_related</alias>
                </action>
        </reference>

最终,这使local.xml成为操作系统的一种非常强大的方法,但是如果你不熟悉它和magento系统,那么就要准备好几周或几个月的工作来真正了解它。

干杯


又一次更新

我现在已经多次遇到这个问题了,我想移动的一个块已被移除。这是一个问题,因为任何已从布局中删除的块都会被永久化。

但是,Alan Storm非常方便Unremove Plugin你可以撤消已经完成的事情:

<checkout_onepage_index>
    <x-unremove name="left" />
    <reference name="right">
        <action method="unsetChild">
            <alias>checkout.progress.wrapper</alias>
        </action>
    </reference>
    <reference name="left">
        <action method="insert">
            <block>checkout.progress.wrapper</block>
        </action>
    </reference>
</checkout_onepage_index>

它通过观察布局对象并构建已删除块的列表来管理此专长,这些块可以在以后引用。

尼斯!

7 个答案:

答案 0 :(得分:19)

现在这是一个尘封的线索,但是为了记录,这是我最后的答案。

<reference name="right">
    <action method="unsetChild">
        <alias>checkout.progress.wrapper</alias>
    </action>
</reference>
<reference name="left">
    <action method="insert">
        <block>checkout.progress.wrapper</block>
    </action>
</reference>

Magento建议在local.xml中加入此内容,并证明这是一种有效的技巧。

答案 1 :(得分:2)

如果您只是希望将输出从2col-right更改为2col-left,那么改变它会更容易,

<reference name="right" ...

<reference name="left" ...

无需取消设置或插入任何子项或重新声明任何内容。你不必要地复杂化和复制代码。

如果您也在制作自己的besoke设计,我建议您开始将整个./app/design/frontend/base目录复制到./app/design/frontend/mypackage - 然后从mypackage/default目录开始重新设置您的网站。它更干净,更容易。如果您复制每个文件(而不仅仅是您想要修改的文件),其他人可能会评论升级能力的潜在问题,但这是一个更好的做法,更不容易出错,困难和一般维护。

修改:要详细跟进此内容,请查看https://magento.stackexchange.com/a/3794/361

答案 2 :(得分:2)

另一种方法是将“右”块重命名为“左”,而不是从右向左移动块。但是,如果首先删除“正确”的块,这将无效,正如我在其他答案中所提出的那样。

<remove name="left" />
<reference name="right">
  <action method="setNameInLayout"><name>left</name></action>
</reference>
<reference name="root">
  <action method="setChild"><alias>left</alias><name>left</name></action>
  <action method="unsetChild"><alias>right</alias></action>
</reference>
<!-- make sure nothing referencing "right" comes after this! -->

答案 3 :(得分:1)

可能会在布局中的某个位置使用<remove name="right" />删除“右侧”块。如果是这样,这将导致“catalog.product.related”块永远不会首先添加到布局中,因此没有块可以插入“左”块。

我很确定这是问题,但要确认,添加一个Mage :: log(“Removed $ blockName”);在for循环中的Mage_Core_Model_Layout-&gt; generateXml()中,并在加载页面后检查日志。

如果我是对的,只需将<block..>复制到local.xml中,然后删除“unsetChild”和“insert”操作。

答案 4 :(得分:1)

我会这样做:在例如

下的local.xml中
<reference name="right"></reference>

删除块,例如:

<remove name="right.poll">

然后在

中添加块
<reference name="left"></reference>

答案 5 :(得分:0)

将base / default复制到本地主题是一个可怕的想法。在Magento版本升级上对核心主题文件的每次更新都会导致修改应用程序/代码/核心文件的相同漏洞 - 需要您在升级时将文件区分开来。

您正确的做法是使用您的添加或覆盖修改单个local.xml。如果这还不够,请使用正确的语法在app / code / community中创建具有布局定义和自定义布局XML文件的模块。

答案 6 :(得分:0)

我认为修改Magento布局的最佳答案在Classyllama.com上给出

http://www.classyllama.com/development/magento-development/the-better-way-to-modify-magento-layout

  

使用remove标记时,无论上下文如何,它都会从整个布局中删除具有指定名称的所有块。因此,如果我在上下文中删除right.newsletter并且在上下文中使用该名称,则将删除这两个块。由于remove在全局上下文中运行,因此您只能删除一次元素。由于在catalogsearch.xml中调用,我们必须取消它,否则我们会收到错误。

<action method="unsetChild"><name>right.newsletter</name></action>;