Magento - переместить блок справа налево - PullRequest
7 голосов
/ 15 марта 2012

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

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

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

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

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

Приветствия


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

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

Однако, с очень удобным 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 ]

19 голосов
/ 22 августа 2012

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

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

2 голосов
/ 16 марта 2012

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

<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! -->
2 голосов
/ 16 марта 2012

Если вы просто и хотите изменить вывод с 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

1 голос
/ 03 мая 2012

Я бы сделал это следующим образом: в вашем local.xml под, например,

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

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

<remove name="right.poll">

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

<reference name="left"></reference>
1 голос
/ 16 марта 2012

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

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

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

0 голосов
/ 09 мая 2012

Я думаю, что лучший ответ для изменения макетов 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>;
0 голосов
/ 16 марта 2012

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

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

...