Magento - move a block from right to left

I don’t know why it is so difficult. If I understand THIS correctly, I must quickly fulfill my goals ... But without joy.

So - I'm building my first theme and still racking my brains over the layout ...

I work specifically on the Catalog Product View page, and I convert this page from the layout of the right column to the layout of the left column. I just want to move the blocks from right to left.

The standard .xml directory defines 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> 

In my local.xml, I'm just trying to move this block:

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

As noted, the catalog.leftnav insert works as expected, so I assume that everything else is configured correctly. The target block displays as expected if I leave the template and other directives unchanged, which tells me that the block should be displayed after it has been correctly deleted and inserted ...

It drives me crazy ... but what else is new with Magento.

Greetings -

B [] x

 UPDATE 

Since I just cannot get the local.xml override to work, I just go back to the modified catalog.xml . I'm a very smart guy ... it bothers me that I can't get this to work (and this purple sound just fails, no matter what happens), but I can't spend more time tricking this stupid problem.

Moving.

 UPDATE, again. 

Some time has passed, now, working in purple and finding out its complexity. Today I returned to this problem, since I need my local.xml to work correctly.

I really don't know that I was wrong, but this set of directives finally worked.

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

The key point that I will tell others about this:

Xml Layout directives call available methods in magento classes. In this case, the Page.xmls "Left" block is of type Mage_Core_Block_Text , which inherits from Mage_Core_Block_Abstract , which contains the unsetChild and insert methods.

from 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; } 

and

  /** * 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; } 

The local xml parameters are important, not in the name (in particular), but in order, that is:

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

This ultimately makes local.xml a really powerful way to manipulate the system, but if you are not familiar with it and the magento system, get ready for weeks or months of work to really think about it.

Greetings


Another update

I ran into a problem several times when the block that I want to move is deleted. This is a problem, since any block that has been removed from the layout is permanently disabled.

However, with Alan Storm it’s very convenient Unremove Plugin you can undo what was done:

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

He manages this feat by observing the layout object and creating a list of deleted blocks that can be referenced later.

Nice!

+7
source share
7 answers

Now this is a dusty thread, but for the record, this is the last answer I went with.

 <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 recommends including this in your local.xml and it has proven to be an effective method.

+19
source

If you just want to change the result from 2col-right to 2col-left, it would be much easier to redo

 <reference name="right" ... 

to

 <reference name="left" ... 

There is no need to disconnect or insert any children or re-announce anything. You overuse things and duplicate code.

If you create your own design yourself, I would suggest starting copying the entire ./app/design/frontend/base directory to ./app/design/frontend/mypackage , and then working from the mypackage/default directory to remake your site. Its cleaner and simpler. Others may comment on potential upgrade issues if you copy each file (and not just the ones you intend to modify), but this is certainly a more efficient practice and much less prone to errors, difficulties and generally maintenance.

Edit: For more on this, see https://magento.stackexchange.com/a/3794/361

+2
source

An alternative approach is to rename the “right” block to “left,” rather than moving the blocks from right to left. However, this will not work if the “right” block is deleted first, as I suggested, maybe in another answer.

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

The "right" block is probably removed with <remove name="right" /> at some point in the layout. If this is the case, this will cause the "catalog.product.related" block to never be added to the layout in the first place, so there is no block to insert into the "left" block.

I'm sure this is a problem, but add Mage :: log ("Deleted $ blockName") for confirmation; in Mage_Core_Model_Layout-> generateXml () inside the for loop and check the log after the page loads.

If I'm right, just copy <block..> into your local.xml file and delete the "unsetChild" and "insert" actions.

+1
source

I would do it this way: in your local.xml for example

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

you delete blocks, for example:

 <remove name="right.poll"> 

and then add blocks to

 <reference name="left"></reference> 
+1
source

Copying the base / default to a local theme is a terrible idea. Each update of the main theme file when updating the Magento version leads to the same vulnerability in changing application / code / kernel files - you need to decompose the files into updates.

Your correct course of action modifies one local.xml file with your additions or overrides. If this is not enough, use the correct syntax to create the module in the application / code / community with your layout definitions and custom layout XML files.

0
source

I think the best answer for changing Magento layouts is on Classyllama.com

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

When using the remove tag, it removes any blocks with the specified name from the entire layout, regardless of context. Therefore, if I delete right.newsletter in the context and this name is used in the context, then both blocks will be deleted. Since remove works in a global context, you can remove one item only once. Since it is called in catalogsearch.xml, we must disable it, otherwise we will get an error.

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

All Articles