Magento - переместить блок справа налево

Не уверен, почему это так сложно. Если я правильно понимаю ЭТО, я смогу быстро достичь своих целей... Но без радости.

Итак, я создаю свою первую тему и все еще думаю о макете...

Я работаю специально над 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.

Ура -

б [] х

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>

Ключевой момент, на который я обращу внимание, для тех, кто занимается этим:

Директивы Layout xml вызывают доступные методы внутри классов magento. В этом случае блок Page.xmls "Left" имеет тип Mage_Core_Block_Text, который наследует от Mage_Core_Block_Abstract который содержит методы unsetChild а также insert,

от 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, будьте готовы к неделям или месяцам работы, чтобы по-настоящему разобраться с ней.

ура


Еще одно обновление

Я столкнулся с проблемой несколько раз, когда блок, который я хочу переместить, был удален. Это проблема, поскольку любой блок, который был удален из макета, обнуляется навсегда.

Однако, с очень удобным плагином Unremove Alan Storm вы можете отменить то, что было сделано:

<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 ответов

Решение

Сейчас это пыльная тема, но, к сведению, это последний ответ, с которым я согласился.

<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и это доказало свою эффективность.

Альтернативный подход состоит в том, чтобы переименовать "правый" блок в "левый", а не перемещать блоки справа налево. Однако, это не будет работать, если "правильный" блок удаляется в первую очередь, как я предположил, может иметь место в моем другом ответе.

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

Если вы просто хотите изменить вывод с 2col-right на 2col-left, было бы намного проще изменить

<reference name="right" ...

в

<reference name="left" ...

Нет необходимости сбрасывать или вставлять какие-либо дочерние элементы или что-либо повторно объявлять. Вы слишком усложняете вещи и дублируете код без необходимости.

Если вы тоже создаете свой собственный дизайн, я бы предложил начать копирование всего ./app/design/frontend/base каталог для ./app/design/frontend/mypackage - тогда работай от mypackage/default каталог для повторного оформления вашего сайта. Это чище и проще. Другие могут прокомментировать потенциальные проблемы, связанные с возможностью обновления, если вы копируете каждый файл (а не только те, которые вы намереваетесь изменить), но это гораздо лучшая практика и гораздо менее подвержена ошибкам, трудностям и общему обслуживанию.

Изменить: чтобы узнать об этом более подробно - посмотрите /questions/11692027/luchshij-sposob-poluchit-innerxml-xelement/11692048#11692048

Я бы сделал это так: в вашем local.xml под eg

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

Вы удаляете блоки, например:

<remove name="right.poll">

а затем вы добавляете блоки в

<reference name="left"></reference>

"Правильный" блок, вероятно, удаляется с <remove name="right" /> в какой-то момент в макете. Если это так, то это приведет к тому, что блок "catalog.product.related" никогда не будет добавлен в макет в первую очередь, поэтому нет блока для вставки в "левый" блок.

Я почти уверен, что это проблема, но для подтверждения добавьте Mage::log("Removed $blockName"); в Mage_Core_Model_Layout->generateXml() внутри цикла for и проверьте журнал после загрузки страницы.

Если я прав, просто скопируйте <block..> в ваш local.xml и удалите действия "unsetChild" и "insert".

Копирование base/default в локальную тему - ужасная идея. Каждое обновление файла основной темы при обновлении версии Magento приводит к одной и той же уязвимости при изменении файлов приложения / кода / ядра - что требует от вас изменения файлов при обновлении.

Ваш правильный курс действий - это изменение одного local.xml с вашими дополнениями или переопределениями. Если этого недостаточно, используйте правильный синтаксис для создания модуля в приложении / коде / сообществе с определениями макетов и XML-файлами пользовательских макетов.

Я думаю, что лучший ответ для изменения макетов Magento дан на Classyllama.com

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

Когда вы используете тег удаления, он удаляет все блоки с указанным именем из всего макета, независимо от контекста. Итак, если я удаляю right.newsletter в контексте и это имя используется, скажем, в контексте, то оба блока будут удалены. Поскольку удаление действует в глобальном контексте, вы можете удалить элемент только один раз. Так как вызывается в catalogsearch.xml, мы должны сбросить его, иначе мы получим ошибку.

<action method="unsetChild"><name>right.newsletter</name></action>;
Другие вопросы по тегам