Magento structural blocks, content blocks and phtml templates - magento

I've just started reading up on Magentos (1.9 CE) layout and how it works with the XML and PHTML files.
I've come across the structural blocks and content blocks.
I'm looking at the page.xml file of Magento 1.9 installed RWD package DEFAULT theme.
I've pasted below what i believe is the header, content, and footer from the page.xml file.
My questions
1) Is a block considered to be a content block the moment it is assigned a "template="XXXX.phtml" attribute? EAnd if not, it is known as a structural block?
2) For structural blocks that don't have the template="XXX", how does it ultimately link with the phtml files? My question comes from the context of looking at the header block as seen below, some of its sub blocks have "template" attribute, but none of them seem to point to the header.phtml from "\template\page\html" directory, which i have been editing to customize the look of the Magento site Welcome message.
<block type="page/html_header" name="header" as="header">
<block type="page/template_links" name="top.links" as="topLinks"/>
<block type="page/switch" name="store_language" as="store_language" template="page/switch/languages.phtml"/>
<block type="core/text_list" name="top.menu" as="topMenu" translate="label">
<label>Navigation Bar</label>
<block type="page/html_topmenu" name="catalog.topnav" template="page/html/topmenu.phtml">
<block type="page/html_topmenu_renderer" name="catalog.topnav.renderer" template="page/html/topmenu/renderer.phtml"/>
</block>
</block>
<block type="page/html_wrapper" name="top.container" as="topContainer" translate="label">
<label>Page Header</label>
<action method="setElementClass"><value>top-container</value></action>
</block>
<block type="page/html_welcome" name="welcome" as="welcome"/>
</block>
<block type="core/text_list" name="content" as="content" translate="label">
<label>Main Content Area</label>
</block>
<block type="page/html_footer" name="footer" as="footer" template="page/html/footer.phtml">
<block type="page/html_wrapper" name="bottom.container" as="bottomContainer" translate="label">
<label>Page Footer</label>
<action method="setElementClass"><value>bottom-container</value></action>
</block>
<block type="page/switch" name="store_switcher" as="store_switcher" after="*" template="page/switch/stores.phtml"/>
<block type="page/template_links" name="footer_links" as="footer_links" template="page/template/links.phtml">
<action method="setTitle"><title>Quick Links</title></action>
</block>
<block type="page/template_links" name="footer_links2" as="footer_links2" template="page/template/links.phtml">
<action method="setTitle"><title>Account</title></action>
</block>
<!-- This static block can be created and populated in admin. The footer_links cms block can be used as a starting point. -->
<!--<block type="cms/block" name="footer_social_links">
<action method="setBlockId"><block_id>footer_social_links</block_id></action>
</block>-->
</block>

There are mainly two types of blocks in Magento
Structural blocks :- These blocks actually defines the structure of a page block. This is where content blocks resides
Example : Header, Left, Right, Footer and Main blocks (defines in page.xml)
Content blocks :- These blocks are actually holding the content. Depends upon the type of block, the content hold by these block varies
Example :- Any custom blocks, core/template block, cms/page block etc.
Normally every content block should come under any of the strucural block that described above. These content block holds different contents depend upon its type. For example, a cms/page block is intend to hold cms page content that we set through admin section. catalog/product_view block is used to hold a product view contents. As you already noted these two content blocks use to hold contents but the content differes from block to block, depending on its type specified. With that said let us look on your problem
1) Structural blocks holds structures of a page. Content block comes under each structual block. So in the above layout code, the block with type page/html_header is a structural block. While all other blocks that come inside this block are content blocks of above structural block. In other words they are children of the header structural block. Now let us look on this header block at backside.
#File : app/code/core/Mage/Page/Block/Html/Header.php
<?php
class Mage_Page_Block_Html_Header extends Mage_Core_Block_Template
{
public function _construct()
{
$this->setTemplate('page/html/header.phtml');
}
......
}
There it is. Our structural block is actually assigned with a template through backend. This means the template that correspond to our header block resides in app/design/frontend/<your_package>/<your_theme>/template/page/html/header.phtml. If you open that file, you can see that the template is actually defining the header portion of our page using html, css and js and invoking its child blocks using a method getChildHtml(). Some portion of above file is shown below.
.....
<div class="quick-access">
<?php echo $this->getChildHtml('topSearch') ?>
<p class="welcome-msg"><?php echo $this->getChildHtml('welcome') ?> <?php echo $this->getAdditionalHtml() ?></p>
<?php echo $this->getChildHtml('topLinks') ?>
<?php echo $this->getChildHtml('store_language') ?>
.....
</div>
.....
As you can see above, it invokes child blocks(in other words content blocks) that are defined in page.xml layout file, using getChildHtml() method.
This means, if you add a custom child block inside the header structural block and didn't invoke it in header.phtml using getChildHtml() method, your content block is not going to show in frontend.
You can also set header.phtml to the block header through page.xml like this
<block type="page/html_header" name="header" as="header" template="page/html/header.phtml" />
There is no issue with this. So in short, we cannot generally say that a block that defines a phtml file is either a content block or a strutural block. How both of these block defferes purely depends on what those block holds.
Short Note : A cotent block can contain other content blocks. What we are doing is most of the time is this. Means adding our custom content block to another content block that already existing in magento.
2) If you look on different blocks in magento, you can see that, irrespective of structural block/content block, a block can set with a template through layout or through backend. We can set template to a block using an observer also. I already stated how header structural block set with the template header.phtml
. In this case it is through backend side.
Hopes that helps you to understand the concept.
EDIT
No you are absoulutely wrong. In magento layout holds the entire structure of a page. It holds all the blocks that need to render for a particular page.
Suppose you have a url www.mydomain.com/index.php/customer/account. What magento does now is it will split the url and find which module generates such url. So here above url split like this
base url => www.mydomain.com/index.php/
frontend name => customer/
action controller name => account/
method => index/
Now magento will query for which module that is responsible for frontend name customer. It is defined by Mage_Customer core module. Now magento look for which controller that handles this url. In our url, the part that mention this is account. So it will look for AccountController.php file in Mage_Customer module. Now again magento look for whcih method that handles the url. But in our url there is no method specified. So it will assume the method index hence. Now look on that method.
#File:app/code/core/Mage/Customer/controllers/AccountController.php
/**
* Default customer account page
*/
public function indexAction()
{
$this->loadLayout();
// some other codes
$this->renderLayout();
}
This is the important section. First the method calls a function loadLayout(). This simple code does a lot of work behind the curton. It will generate a big layout tree that is correspond to the page that is going to show in frontend. Where is this layouts are defined ? Of course.. It is in layout XML files. Layout xml file defines what are the blocks that should render for this above url and what are not. For an example in this context, follwing handles will be processed by magento.
default
STORE_default
THEME_frontend_default_default
customer_account_index
customer_logged_in
customer_account
Magento will generate a huge layout tree that will consist of all blocks that is specified under these layout handles. Layout handles may come in any layout XML file that comes under the directory app/design/frontend/<your_package>/<your_theme>/layout. After creating this layout tree, magento will render these layout tree using the code renderLayout(). Basically what it will do is convert these layout into html and render it (For this it uses template files and skin).
Now what would you think ? Layout XMLs are that simple? :)

Related

How link a menu group in magento (via blocks/.phtml files)

I have created a mega menu group. but i stuck at relating it to file.
All i can see form a default one is
<block type="core/text_list" name="megamenu_left" as="megamenu_left" translate="label">
<label>Left Megamenu</label>
</block>
In Home page(Backend > Design Section):
<reference name="megamenu_left">
<block type="megamenu/list" name="megamenu.list.theme" as="megaMenuLeft" template="sm/megamenu/megamenu-left.phtml">
<action method="setConfig">
<values>
<group_id>2</group_id>
<theme>2</theme>
</values>
</action>
</block>
</reference>
And in home page Front view:
<?php echo $this->getChildHtml('megamenu_left') ?>
Things i didn't get is name="megamenu.list.theme" and how this is rendering.
EDITED
how is 'megamenu_left' from xml above is linked with a menu group i created on the backend. The menu group i created on backend just have a name and 'enable/disable' option.
I'm not sure if I understand the question correctly, but the second XML bit is going to look for the reference "megamenu_left" found in the first XML part, and insert the block at that position.
The block itself has the full name "megamenu.list.theme" in the layout, with the optional shortname "megaMenuLeft". It will render the template file "sm/megamenu/megamenu-left.phtml" which will be positioned in the active theme folder such as "app/design/frontend/theme/..".
The template will be using the PHP block from module "megamenu/Block/List.php" so any $this->functionName() calls or variables accessed from within the function comes from that block.
The frontpage will load the block by name from the first part of XML, which in turn will get the content from the second part XML since it's a reference, meaning it will insert itself in the first XML.

Showing custom static block on the custom page Magento

I have a some question about Magento cms static block showing on the custom page.
For example, I have 3 static block (block 1, block 2, block 3) and I need to display block 1 at the Category 1 and subcategories 1, block 2 at the Category 2 and subcategories 2, and block 3 at other pages (home, about, etc)
I try to use Mage::app()->getFrontController()->getRequest()->getRequestUri()
But I received request like "category1.html" and if we going to subcategory of this category - block is changed to default.
If use Mage::app()->getFrontController()->getRequest() I received "catalog/category/view/id/id_number"
I really don't understand how to solve this issue.
Thanks for answer!
You can add a block to a specific part of the page, for a specific category using the Custom Layout Update functionality.
NOTE: If you have a custom theme, the reference name for the footer could be different. This method has been tested to work on the Modern theme included with Magento
Go to Catalog > Manage Categories
Choose the category you want to assign your block to.
Go to the Custom Design tab.
Set Use Parent Category Settings to No
In the Custom Layout Update, insert the following XML
<reference name="bottom.container">
<block type="cms/block" name="my_footer_block">
<action method="setBlockId">
<block_id>my_footer_block</block_id>
</action>
</block>
</reference>
Replace my_footer_block with the Identifier (block_id) of your static block.
Clear your Magento Caches under System > Cache Management and refresh the Category page.
If this does not work, the reference name may not be correct for the theme you are using. You can check the reference name by looking under app/design/frontend/[THEME PARENT]/[THEME CHILD]/layout/page.xml and searching for page/html_footer within the file.
In the file, you will find something like this:
<block type="page/html_footer" name="footer" as="footer" template="page/html/footer.phtml">
<block type="page/html_wrapper" name="bottom.container" as="bottomContainer" translate="label">
<label>Page Footer</label>
<action method="setElementClass"><value>bottom-container</value></action>
</block>
<block type="page/template_links" name="footer_links" as="footer_links" template="page/template/links.phtml"/>
<block type="page/switch" name="store_switcher" as="store_switcher" template="page/switch/stores.phtml"/>
</block>
<block type="core/text_list" name="before_body_end" as="before_body_end" translate="label">
<label>Page Bottom</label>
</block>
</block>
Note the name attribute for the page/html_wrapper block. This is the name references used in the code provided in step Step 5. If it's different than bottom.container, change bottom.container to match what is in your page.xml file.
this might help you
Strategy : Check current page is whether current category is available on current page or not, If available then you can check it's level and depending on that you can show you block
Solution :
$_current_category=$this->getCurrentCategory();
1)get current category and if category not available then show default block
2)if category found get it's level $_current_category->getLevel() and then you can place your block accordingly
Override catalog.xml in you local module
Add in
in content reference
in you catalog/category/voew.phtml
add this code
$_current_category=$this->getCurrentCategory();
if(cond == '1st category') {
echo $this->getChildHtml('block1');
}
Similarly for other blocks
You can simply assign a static block to specific categories using the built in functionality Magento provides.
Go to Catalog > Manage Categories
Click the category you want to assign the block to on the left.
Go to the Display Settings tab
Set Display Mode to either Static block only or Static block with products.
Set CMS Block to the static block you want to display on this category.
Click the Save Category button.
Repeat this step for different categories. You can choose a unique static block, or assign the same one to multiple categories this way.

How can I display a magento block in more than one location?

I'm trying to display the cross sell block in it's normal location as well as at the bottom of the page. There is more than one phtml template file involved so $this->getChildHtml does not work in the second location since the block is setup to only be on the cart.phtml file as of now.
In summary, how can I display the same block in more than one template file? I wan't to place these changes in my local.xml and do not want to modify core Magento template files.
The core layout directive for this block is set up as a child of the checkout.cart block:
<checkout_cart_index translate="label">
<!-- ... -->
<reference name="content">
<block type="checkout/cart" name="checkout.cart">
<!-- ... -->
<block type="checkout/cart_crosssell" name="checkout.cart.crosssell" as="crosssell" template="checkout/cart/crosssell.phtml"/>
</block>
</reference>
</checkout_cart_index>
To add it to the footer, you might need to only establish another parent-child relationship in your local.xml:
<checkout_cart_index>
<reference name="footer">
<action method="insert"><!-- or "append" to add to the end -->
<child>checkout.cart.crosssell</child>
</action>
</reference>
</checkout_cart_index>
This approach relies on the stock page/html/footer.phtml template which contains an empty getChildHtml() call, which causes it to render all child blocks.
Note that the footer block class Mage_Page_Block_Html_Footer has a never-expiring block_html cache lifetime, and it does not evaluate child contents for its cache entry. You may need to disable the cache for this block or rewrite the block class to account for the varied content of the crosssell block.

Magento - moving extension from left/right column to main

I try to move an ext: Customers who bought this product also purchased from default left/right column to main column under the product, but I don't know how to do this.
I try to change the line <product_detail_leftposition translate="label"> to <product_page translate="label"> in system.xml file but it doesn't help.
Any suggestions?
Thanks for any help!
You can do this by adding it to the Products view page section inside your layout XML. Add the block inside the content reference block, somewhere at the bottom.
Make sure it's inside the handle as this defines the structure used on the product view page.
app/design/frontend/[namespace]/[themename]/layout/catalog.xml
<catalog_product_view translate="label">
...
<reference name="content">
...
<block type="catalog/product_view" name="product.info" template="catalog/product/view.phtml">
<!-- Other blocks etc here.. add at the bottom -->
<block type="module/block" name="yourblock" as="yourblock" />
</block>
</reference>
</catalog_product_view>
This should automatically output the block for you if you add it in here, although that depends on the theme you are using.
if it doesn't automatically show, you may need to add a line to your view to display the block:
app/design/frontend/[namespace]/[themename]/template/catalog/product/view.phtml
<?php // use the block name used in the XML config.. ?>
<?php echo $this->getChildHtml('yourblock') ?>

What Block Type for Left Column in Magento Theme?

I'm working on a custom Magento (1.3) theme and am wanting to add a left column.
I've created template/page/html/left.phtml with the html in.
In 2columns-left.phtml, i've added the following:
<?php echo $this->getChildHtml('left'); ?>
In page.xml, i've added the following:
<block type="page/html" name="left" as="left" template="page/html/left.phtml" />
What i'm not quite understanding is what that block type should be - it seems to work if I do page/html, core/template or page/html_header - what is this for and what is the correct value for this case, where I just want to effectively include a phtml file - page/html/left.phtml etc.
Thanks,
Ian
This is a simplified version of what's going on, but will
hopefully be enough to get you going.
Special Objects
There are three types of Objects that Magento considers "special". These are Models, Blocks, and Helpers. Rather than use class names for these objects Magento uses URI-like strings called class aliases . So this
page/html
corresponds to the Block class
Mage_Page_Block_Html
Class here is referring to PHP classes, not CSS classes.
Magento Page Rendering
A Layout Object is responsible for creating all the HTML for a Magento page.
A Layout Object is a collection of nested Block Objects.
Most Block Objects are Template Blocks, that is, the Block class inherits from the base Magento template block Mage_Core_Block_Template. Template Blocks are objects responsible for rendering a phtml template file.
So, when you specify a "type" in the XML Layout files, you're telling Magento.
I want to add a block object with the class foo/bar, using the template baz.phtml
In code, that's
<!-- "name" and "as" are used to identify the block in the layout, so that
PHP code can get a reference to the object. -->
<block type="foo/bar" name="myname" as="myname" template="path/to/baz.phtml" />
If all you want to do is render a template file, you can use
type="core/template"
However, by using a different value, like
type="page/html"
your phtml template file gets access to all the methods in
Mage_Page_Block_Html
Which means you could do something like
File: template.phtml
The core/template class doesn't have a getBaseUrl method, but the page/html class does.
If you're doing custom module development (as opposed to just theming), I usually create a Block Object in my own module that extends one of the base Magento blocks. This allows me to add my own methods to the block as I see fit. If you're only theming, page/html is a decent default.
The best type for this case is core/text_list because it concatenates every child HTML.
For testing you could use this example in your layout XML:
<block type="core/text_list" name="left" as="left">
<block type="core/text" name="test">
<action method="setText"><text>Hello World</text></action>
</block>
</block>
Block type for left column in magento theme
<block type="core/text_list" name="left" as="left" translate="label">
<label>Left Column</label>
</block>

Resources