Upload
magecom-ukraine
View
2.556
Download
1
Embed Size (px)
Citation preview
Magento rendering system
Vitaliy GolomoziyConsultantMagento Inc.
What is rendering ?
We understand rendering as a process of generating output for the customer.
Client
Server
Web
GET index.php HTTP/1.1Host: somehos.com
HTTP/1.1 200 OK...
<html><head>
...
Two goals of rendering output in webGenerate headersGenerate response body
How it works in magento ?
Front (Mage_Core_Controller_Varien_Front::dispatch) contoller calls $response->sendResponse()
Response object (Mage_Core_Controller_Response_Http which extends Zend_Controller_Response_Http) calls sendHeaders and outputBody
So, the main goal of rendering system is to generate html bodyand assign it to response object body variable
Actors (Magento View Level)
Template and layout configuration files organization
app
designarea (adminhtml or frontend)
package (default, enterprise)theme (default, mytheme)
layout
templatecage.xml, catalog.xml, etc..
template files (.phtml)
Generating output flowController sets body directly to response object.
Example: Mage_Adminhtml_CustomerController::ordersActionpublic function ordersAction() { $this->_initCustomer(); $this->getResponse()->setBody( $this->getLayout() ->createBlock('adminhtml/customer_edit_tab_orders') ->toHtml() ); }
Controller calls loadLayout(), renderLayout()Most of controllers follows this way. For example Mage_Adminhtml_Catalog_ProductController::indexAction public function indexAction() { $this->_title($this->__('Catalog')) ->_title($this->__('Manage Products'));
$this->loadLayout(); $this->_setActiveMenu('catalog/products'); $this->renderLayout(); }
Loading layout
Layout configuration file structure
Layout configuration is an xml file.Root node is - <layout>First-level node is arbitrary node which named “handle”Second-level node is <block> or <reference>Block attributes: name, type, output, template, as, translateReference attributes: name
Block children: block or actionAction attributes: method, ifconfig, blockAction children: any flat node.Action children attribute: helper
Reference children: block, action
Layout configuration file example
<layout version="0.1.0">
<default translate="label" module="page"> <label>All Pages</label> <block type="page/html" name="root" output="toHtml" template="page/3columns.phtml"> <block type="page/html_head" name="head" as="head"> <action method="addJs"><script>prototype/prototype.js</script></action> <action method="addJs" ifconfig="dev/js/deprecation"> <script>prototype/deprecation.js</script></action> <action method="addJs"><script>lib/ccard.js</script></action> ........................... </default>
Building layout example
<block name=”root”> <block name=”head”> <action method=”doSomething> <some>_VALUE_</some> </action> </block>
<block name=”header”> </block>
<block name=”content”> ..... <block name=”somebock” type=”A”> .... </block> </block></block>
<block name=”root”> <block name=”head”> <action method=”doSomething”> <some>_VALUE_</some> </action> </block>
<block name=”header”> </block>
<block name=”content”> ..... </block></block>
<reference name=”content”> <block name=”somebock” type=”A”> .... </block></reference>
default
FullActionName catalog_product_view
$root = new Block();$head = new Block();$head->doSomething(_VALUE_);
$root->addChild($head);
$header = new Block();
$content = new Block();
$someblock = new A();$content->addChild($someblock);
Render layout schema
Looking for template file
1) In current theme (store config: default/design/theme/template)2) In fallback theme (store config: default/design/theme/default)3) In “default” theme4) In “base” package “default” theme
First of all package established (store config: default/design/package)
Then template file is searching in the following places:
Block_Template fetchView method $do = $this->getDirectOutput(); if (!$do) { ob_start(); }
if ($this->getShowTemplateHints()) { ... }
try { $includeFilePath = realpath($this->_viewDir . DS . $fileName); if (strpos($includeFilePath, realpath($this->_viewDir)) === 0) { include $includeFilePath; } else { Mage::log('Not valid template file:'.$fileName, Zend_Log::CRIT, null, null, true); }
} catch (Exception $e) { ob_get_clean(); throw $e; }
if ($this->getShowTemplateHints()) { echo '</div>'; }
if (!$do) { $html = ob_get_clean(); } else { $html = ''; } ....
Corollary
Template execution is direct include inside Block_Template fetchViewmethod. It means that “$this” inside template refers to correspondent block instance
Each template file has own block instance which extends Mage_Core_Block_Template class.
Magento (almost) never renders children of the block. Exception isMage_Core_Block_Text_List class.
There are 4 places where real template file could be located (current theme, fallback theme, default theme, base package default theme). Moreover if two appropriate file exists, first from the above list will be taken, which gives flexibility in overriding native templates.
Root template example
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->getLang() ?>" lang="<?php echo $this->getLang() ?>"><head><?php echo $this->getChildHtml('head') ?></head><body<?php echo $this->getBodyClass()?' class="'.$this->getBodyClass().'"':'' ?>><?php echo $this->getChildHtml('after_body_start') ?><div class="wrapper"> <?php echo $this->getChildHtml('global_notices') ?> <div class="page"> <?php echo $this->getChildHtml('header') ?>
<div class="main-container col3-layout"> <div class="main"> <?php echo $this->getChildHtml('breadcrumbs') ?> <div class="col-wrapper"> <div class="col-main"> <?php echo $this->getChildHtml('global_messages') ?> <?php echo $this->getChildHtml('content') ?> </div> <div class="col-left sidebar"><?php echo $this->getChildHtml('left') ?></div> </div> <div class="col-right sidebar"><?php echo $this->getChildHtml('right') ?></div> </div> </div> <?php echo $this->getChildHtml('footer') ?> <?php echo $this->getChildHtml('before_body_end') ?> </div></div><?php echo $this->getAbsoluteFooter() ?></body></html>
app/desig/frontend/base/default/template/page/3columns.phtml
Other ways for rendering childrenExtend your block from Mage_Core_Block_Text_List.
class Mage_Core_Block_Text_List extends Mage_Core_Block_Text{ protected function _toHtml() { $this->setText(''); foreach ($this->getSortedChildren() as $name) { $block = $this->getLayout()->getBlock($name); if (!$block) { Mage::throwException(Mage::helper('core')->__('Invalid block: %s', $name)); } $this->addText($block->toHtml()); } return parent::_toHtml(); }}
Call getChildHtml('') without parameters. public function getChildHtml($name='', $useCache=true, $sorted=false) { if ('' === $name) { ... foreach ($children as $child) { $out .= $this->_getChildHtml($child->getBlockAlias(), $useCache); } return $out;
} else { ... }
The End