8

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

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

我专门在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[]x

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 插件,您可以撤消已完成的操作:

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

它通过观察布局对象来管理这一壮举,并构建一个已删除块的列表,以后可以引用该列表。

好的!

4

7 回答 7

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

于 2012-08-22T16:08:08.813 回答
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! -->
于 2012-03-15T22:43:36.100 回答
2

如果您只是想将输出从 2col-right 更改为 2col-left,那么更改会容易得多

<reference name="right" ...

<reference name="left" ...

无需取消设置或插入任何子项或重新声明任何内容。您使事情变得过于复杂并不必要地重复代码。

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

编辑:要更详细地跟进这一点 - 看看https://magento.stackexchange.com/a/3794/361

于 2012-03-15T20:00:03.653 回答
1

我会这样做:在你的 local.xml 下,例如

<reference name="right"></reference>

您删除块,例如:

<remove name="right.poll">

然后你添加块

<reference name="left"></reference>
于 2012-05-03T15:49:14.917 回答
1

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

我很确定这是问题所在,但要确认,请添加 Mage::log("Removed $blockName"); 在 for 循环内的 Mage_Core_Model_Layout->generateXml() 中,并在加载页面后检查日志。

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

于 2012-03-15T22:23:48.810 回答
0

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

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

于 2012-03-15T21:47:17.767 回答
0

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

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>;
于 2012-05-08T20:51:02.703 回答