解析顺序

布局xml文件一般位于app/design/{area}/{package}/{theme}/layout/目录下。Layout文件一般包含block、reference、action三种标签。

对于Magento系统,首先会将系统中相关相关的layout合并,合并一般是包括app\design\frontend\base \default\layout目录下的xml文件,以及指定的模板下面的对应的layout文件。最终普通网页合并之后的从default下 output=”toHtml”进行最终的输出,那么解析的block或其他元素也是从该节点进行解析。

1.顶层的block一般位于page.xml中,如下所示。Output表示通过toHtml进行输出。默认使用3columns.phtml三列布局。Type对应Mage_Page_Block_Html类。

  1. <block type="page/html" name="root" output="toHtml" template="page/3columns.phtml">

2.在顶层的block中,一般包含以下几个关键部分,分别是Html头部、网页头部、内容左部中部右部、网页底部这么几个基本结构布局。

  1. <block type="page/html_head" name="head" as="head">
  2. <block type="page/html_header" name="header" as="header">
  3. <block type="page/html_breadcrumbs" name="breadcrumbs" as="breadcrumbs"/>
  4. <block type="core/text_list" name="left" as="left" translate="label">
  5. <block type="core/text_list" name="content" as="content" translate="label">
  6. <block type="core/text_list" name="right" as="right" translate="label">
  7. <block type="page/html_footer" name="footer" as="footer" template="page/html/footer.phtml">

3.每个模块一般情况下都会有对应的模块xml文件,如目录布局文件为catalog.xml文件,支付为checkout.xml。不过对于magento系统来说,最终还是合并读取的。

4.如果是目录模块被调用,在catalog.xml中,首先会将default节点中所有元素进行加载和解析,然后根据对应产品模块具体页面加载 对应的节点,如分类文件默认采用catalog_category_default节点下的元素更新,如果分类设置为Is Anchor,则采用catalog_category_layered节点下的元素更新。产品默认采用catalog_product_view节点下 的元素更新。

现在我们详细的分析一下page中的各个布局结构

1.Html头部:Html头部主要包括增加默认的js和css相关文件。

  1. <block type="page/html_head" name="head" as="head">
  2. <action method="addJs"><script>prototype/prototype.js</script></action>
  3. <action method="addCss"><stylesheet>css/styles.css</stylesheet></action>
  4. </block>

2.页面头部:主要包括一些头部链接、语言切换等

  1. <block type="page/html_header" name="header" as="header">
  2. <block type="page/template_links" name="top.links" as="topLinks"/>
  3. <block type="page/switch" name="store_language" as="store_language" template="page/switch/languages.phtml"/>
  4. <block type="core/text_list" name="top.menu" as="topMenu" translate="label">
  5. <label>Navigation Bar</label>
  6. </block>
  7. <block type="page/html_wrapper" name="top.container" as="topContainer" translate="label">
  8. <label>Page Header</label>
  9. <action method="setElementClass"><value>top-container</value></action>
  10. </block>
  11. </block>

3.左右部侧栏,一般有product_compare_sidebar、catalog.leftnav、catalog.product.related等侧边栏,具体需要看对应页面的所对应的侧边栏。

4.content内容一般在具体页面中进行指定,不同模块的内容肯定是不同的,在page.xml文件中只是定义了一个as。

5.footer包括了切换store、常见链接等。

解析内容

布局xml文件一般位于app/design/{area}/{package}/{theme}/layout/目录下。Layout文件一般包含block、reference、action三种标签。

1.Block标签指明对应的Html数据块,在指定是一个Block后,系统首先会根据该Block的配置生成一个html数据块,然后再继续解析它所包含的其他内容。

  1. <block type="checkout/cart_sidebar" name="cart_sidebar" template="checkout/cart/sidebar.phtml" before="-">
  2. <action method="addItemRender"><type>configurable</type><block>checkout/cart_item_renderer_configurable</block><template>checkout/cart/sidebar/default.phtml</template></action>
  3. <block type="core/text_list" name="cart_sidebar.extra_actions" as="extra_actions" translate="label" module="checkout">
  4. <label>Shopping Cart Sidebar Extra Actions</label>
  5. </block>
  6. </block>

如在解析type=”checkout/cart_sidebar”
block的时候,首先在config.xml找到checkout的block所对应的半类名,得到Mage_Checkout_Block,再和
cart_sidebar组成全称类名为Mage_Checkout_Block_Cart_Sidebar,该Block类所对应的模板文件为
checkout/cart/sidebar.phtml,before=”-”表明在同级别上,它是排在最前面的。Name需要唯一,作为解析和引用使
用。

然后在解析子Block时候,如type=”core/text_list”的Block,会告诉他的父节点cart_sidebar该子节点信息,这
样,在父节点所对应的模板文件中,才能使用getChildHtml(“cart_sidebar.extra_actions”)函数调用子节点的
html信息。
如果有as节点,表示该节点可以在其他地方被引用,也就是说可以在其他地方再次解析,比如as=’left’,则可以在其他地方用reference中进行添加相关block操作。

2.Reference标签指明其他Block
Name在该区域的一个引用,Reference所对应的Block一般都有as属性。一般也只有一个name值,表示这一Block会使用该
Reference填充内容,将该Reference下的子Block作为对应Blok的子Block进行解析。

3.Action表明指定的Block执行一些特别的动作,比如添加js,css,给常量赋值,调用Block中对应的函数等。

  1. <block type="core/template" name="right.permanent.callout" template="callouts/right_col.phtml">
  2. <action method="setImgSrc"><src>images/media/col_right_callout.jpg</src></action>
  3. <action method="setImgAlt" translate="alt" module="catalog"><alt>Keep your eyes open for our special Back to School items and save A LOT!</alt></action>
  4. </block>

在Block当中调用Mage_Core_Block_Template类解析callouts/right_col.phtml。在该block
下的action中,没有指定节点,表明该action作用于上级Block即right.permanent.callout。在方法中使用
setImgSrc函数,那么对应的,可以在模板中使用getImgSrc获取到action中所包含的值。

在setImgAlt中,也可以使用getImgAlt获取值,不过其中使用translate属性和module属性,那么会调用Catalog中的Helper,对alt中的内容进行翻译成对应的本地化文字。

附:

  1. * Create layout blocks from configuration
  2. *
  3. * @param Mage_Core_Layout_Element|null $parent
  4. */
  5. public function generateBlocks($parent=null)//Mage_Core_Model_Layout
  6. {
  7. if (emptyempty($parent)) {
  8. $parent = $this->getNode();
  9. }
  10. foreach ($parent as $node) {
  11. $attributes = $node->attributes();
  12. if ((bool)$attributes->ignore) {
  13. continue;
  14. }
  15. switch ($node->getName()) {
  16. case 'block':
  17. $this->_generateBlock($node, $parent);
  18. $this->generateBlocks($node);
  19. break;
  20. case 'reference':
  21. $this->generateBlocks($node);
  22. break;
  23. case 'action':
  24. $this->_generateAction($node, $parent);
  25. break;
  26. }
  27. }
  28. }
  29. protected function _generateBlock($node, $parent)
  30. {
  31. if (!emptyempty($node['class'])) {
  32. $className = (string)$node['class'];
  33. } else {
  34. $className = Mage::getConfig()->getBlockClassName((string)$node['type']);
  35. }
  36. $blockName = (string)$node['name'];
  37. $_profilerKey = 'BLOCK: '.$blockName;
  38. Varien_Profiler::start($_profilerKey);
  39. $block = $this->addBlock($className, $blockName);
  40. if (!$block) {
  41. return $this;
  42. }
  43. if (!emptyempty($node['parent'])) {
  44. $parentBlock = $this->getBlock((string)$node['parent']);
  45. } else {
  46. $parentName = $parent->getBlockName();
  47. if (!emptyempty($parentName)) {
  48. $parentBlock = $this->getBlock($parentName);
  49. }
  50. }
  51. if (!emptyempty($parentBlock)) {
  52. $alias = isset($node['as']) ? (string)$node['as'] : '';
  53. if (isset($node['before'])) {
  54. $sibling = (string)$node['before'];
  55. if ('-'===$sibling) {
  56. $sibling = '';
  57. }
  58. $parentBlock->insert($block, $sibling, false, $alias);
  59. } elseif (isset($node['after'])) {
  60. $sibling = (string)$node['after'];
  61. if ('-'===$sibling) {
  62. $sibling = '';
  63. }
  64. $parentBlock->insert($block, $sibling, true, $alias);
  65. } else {
  66. $parentBlock->append($block, $alias);
  67. }
  68. }
  69. if (!emptyempty($node['template'])) {
  70. $block->setTemplate((string)$node['template']);
  71. }
  72. if (!emptyempty($node['output'])) {
  73. $method = (string)$node['output'];
  74. $this->addOutputBlock($blockName, $method);
  75. }
  76. Varien_Profiler::stop($_profilerKey);
  77. return $this;
  78. }
  79. protected function _generateAction($node, $parent)
  80. {
  81. if (isset($node['ifconfig']) && ($configPath = (string)$node['ifconfig'])) {
  82. if (!Mage::getStoreConfigFlag($configPath)) {
  83. return $this;
  84. }
  85. }
  86. $method = (string)$node['method'];
  87. if (!emptyempty($node['block'])) {
  88. $parentName = (string)$node['block'];
  89. } else {
  90. $parentName = $parent->getBlockName();
  91. }
  92. $_profilerKey = 'BLOCK ACTION: '.$parentName.' -> '.$method;
  93. Varien_Profiler::start($_profilerKey);
  94. if (!emptyempty($parentName)) {
  95. $block = $this->getBlock($parentName);
  96. }
  97. if (!emptyempty($block)) {
  98. $args = (array)$node->children();
  99. unset($args['@attributes']);
  100. foreach ($args as $key => $arg) {
  101. if (($arg instanceof Mage_Core_Model_Layout_Element)) {
  102. if (isset($arg['helper'])) {
  103. $helperName = explode('/', (string)$arg['helper']);
  104. $helperMethod = array_pop($helperName);
  105. $helperName = implode('/', $helperName);
  106. $arg = $arg->asArray();
  107. unset($arg['@']);
  108. $args[$key] = call_user_func_array(array(Mage::helper($helperName), $helperMethod), $arg);
  109. } else {
  110. /**
  111. * if there is no helper we hope that this is assoc array
  112. */
  113. $arr = array();
  114. foreach($arg as $subkey => $value) {
  115. $arr[(string)$subkey] = $value->asArray();
  116. }
  117. if (!emptyempty($arr)) {
  118. $args[$key] = $arr;
  119. }
  120. }
  121. }
  122. }
  123. if (isset($node['json'])) {
  124. $json = explode(' ', (string)$node['json']);
  125. foreach ($json as $arg) {
  126. $args[$arg] = Mage::helper('core')->jsonDecode($args[$arg]);
  127. }
  128. }
  129. $this->_translateLayoutNode($node, $args);
  130. call_user_func_array(array($block, $method), $args);
  131. }
  132. Varien_Profiler::stop($_profilerKey);
  133. return $this;
  134. }

在addJs、addCss的代码一般在page/html_head类型的block当中,Magento首先会将所有文件存储在$_data当中,最终通过getCssJsHtml函数解析成对应的html代码输出。

Head中支持add类型的方法有addCss、addJs、addCssIe、addJsIe、addLinkRel五种。

  1. <reference name="head">
  2. <action method="addCss"><stylesheet>css/local.css</stylesheet></action>
  3. <action method="addJs"><script>scriptaculous/controls.js</script></action>
  4. <action method="addItem"><type>js</type><name>lib/ds-sleight.js</name><params/><if>lt IE 7</if></action>
  5. </reference>

通用的函数是addItem,需要指定type和name,如果有条件判断的话就放在if标签当中

如果需要删除某个js或者css,可以使用removeItem方法

jslib/ds-sleight.js

其他的action函数需要看其type所对应的类中所支持的函数。

  1. /**
  2. * Get HEAD HTML with CSS/JS/RSS definitions
  3. * (actually it also renders other elements, TODO: fix it up or rename this method)
  4. *
  5. * @return string
  6. */
  7. public function getCssJsHtml()//Mage_Page_Block_Html_Head extends Mage_Core_Block_Template
  8. {
  9. // separate items by types
  10. $lines  = array();
  11. foreach ($this->_data['items'] as $item) {
  12. if (!is_null($item['cond']) && !$this->getData($item['cond']) || !isset($item['name'])) {
  13. continue;
  14. }
  15. $if     = !emptyempty($item['if']) ? $item['if'] : '';
  16. $params = !emptyempty($item['params']) ? $item['params'] : '';
  17. switch ($item['type']) {
  18. case 'js':        // js/*.js
  19. case 'skin_js':   // skin/*/*.js
  20. case 'js_css':    // js/*.css
  21. case 'skin_css':  // skin/*/*.css
  22. $lines[$if][$item['type']][$params][$item['name']] = $item['name'];
  23. break;
  24. default:
  25. $this->_separateOtherHtmlHeadElements($lines, $if, $item['type'], $params, $item['name'], $item);
  26. break;
  27. }
  28. }
  29. // prepare HTML
  30. $shouldMergeJs = Mage::getStoreConfigFlag('dev/js/merge_files');
  31. $shouldMergeCss = Mage::getStoreConfigFlag('dev/css/merge_css_files');
  32. $html   = '';
  33. foreach ($lines as $if => $items) {
  34. if (emptyempty($items)) {
  35. continue;
  36. }
  37. if (!emptyempty($if)) {
  38. $html .= '<!--[if '.$if.']>'."\n";
  39. }
  40. // static and skin css
  41. $html .= $this->_prepareStaticAndSkinElements('<link rel="stylesheet" type="text/css" href="%s"%s />' . "\n",
  42. emptyempty($items['js_css']) ? array() : $items['js_css'],
  43. emptyempty($items['skin_css']) ? array() : $items['skin_css'],
  44. $shouldMergeCss ? array(Mage::getDesign(), 'getMergedCssUrl') : null
  45. );
  46. // static and skin javascripts
  47. $html .= $this->_prepareStaticAndSkinElements('<script type="text/javascript" src="%s"%s></script>' . "\n",
  48. emptyempty($items['js']) ? array() : $items['js'],
  49. emptyempty($items['skin_js']) ? array() : $items['skin_js'],
  50. $shouldMergeJs ? array(Mage::getDesign(), 'getMergedJsUrl') : null
  51. );
  52. // other stuff
  53. if (!emptyempty($items['other'])) {
  54. $html .= $this->_prepareOtherHtmlHeadElements($items['other']) . "\n";
  55. }
  56. if (!emptyempty($if)) {
  57. $html .= '<![endif]-->'."\n";
  58. }
  59. }
  60. return $html;
  61. }

布局原理解析

Magento中的布局(Layout)包含一小部分的标记集合,作为详细说明关于程序如何建立一个页面,如何建立它的行为和每个构建的区块。最佳 的布局途径是在每个角度正确的划分和使用。为了让您能够做到这一点,下面是一些行为特性的布局XML标记。


句柄(Handle)

Handle (图1)是一个标识符,决定应用程序要如何通过嵌套的更新处理它。

如果句柄的名称是<default>,然后应用程序知道在加载网店的几乎所有页面之前应该加载此特定页面布局的嵌套更新(我们说'几乎 所有的',因为一些特殊的页面像产品图片弹出窗口就没有加载布局中的<default>句柄)。

如果Magento找到<default>以外的句柄,它将按照指定的句柄中的页面嵌套更新对页面进行处理。例
如,<catalog_product_view>包含Product
View页面的布局更新,而<catalog_product_compare_index>包含Compare Product
页面的更新布局。句柄作为设计人员设置在网店中的标识符,他不需要广泛的理解 Magento编程,也不应该需要修改。


<block>

Magento通过<block>标记决定页面中的每个区块的行为和视觉表现。在Magento中我们已经提到了两种类型的区块-结
构区块(structural blocks)和内 容区块(content
blocks)。区分这两种区块最好的方式是通过分配给它的标记属性来区分。结构区块通常包含属性'as',通过这个属
性值程序可以与指定的区域(由getChildHtml
方法指定)中的模板联系。你会发现在默认布局许多地方出现这个'as'属性,因为默认布局的一个性质就是是建立一个实际的布局,在各个不同的页面
中的具体布局上就可以开始增加。例如,在默认布局中,有像‘left’、‘right’、‘content’和‘footer’这些结构区块。并不是说这
些区块不能存在于正常的布局更新中,但我们为什么不首先在默认布局中建立这些结构区块,然后在后面每个具体的页面基础上添加内容呢?让我们进一步挖
掘<block>的现有属性。

  • type
    – 这是模块类的标识符,它定义了区块的功能。此属性不应该被修改。
  • name
    – 这是名称,其他的区块可以通过此名称引用此区块(看图3)。
  • before
    (and) after
    – 这两种方法决定内容区块在结构区块中的位置。before="-" 和 after="-"这样的命令标志此区块的位置是一个结构区块的最上方或最下方。
  • template
    - 这个属性指定的值决定了此区块的功能是使用哪个模板。例如,如果这个属性值指定了'catalog/category/view.phtml
    ', 程序就会载入‘app/design/frontend/template/catalog/category/view.phtml
    ’ 模板文件。要了解布局是如何通过模板执行的,阅读分 步指南建设一个主题。
  • action
    – <action> 是用来控制前台的功能的,如加载或不加载一个JavaScript。一套完整的action方式将很快推出,但此时的最佳的学习途径是了解现有的布局更新 上面的不同Action方法。
  • as
    – 此属性指 定模板文件中会调用那个区块。当您在模板中看到getChildHtml('
    block_name ')的PHP方法,可以肯定它指的是引用属性'as'的值为' block_name '的区块。
    (例如:在骨架模板中的方法<?=$this->getChildHtml('header')?>是调用<block
    as=“header”>)

<reference>

<reference>是用来引用另一个区块。要引用灵位一个区块,在内部的更新将应用于与其关联的<block>(见图 3)。

要使用引用,可以通过区块中的‘name’属性值引用。此属性的指向标签中'name'属性。所以,如果你使用<reference name="right">,响应的区块名称将是<block name="right">。

图3:

来源:http://www.ahuasheng.com/magento-layout-xml-parse-content.html

Magento布局layout.xml文件详解的更多相关文章

  1. 史上最全的maven的pom.xml文件详解(转载)

    此文出处:史上最全的maven的pom.xml文件详解——阿豪聊干货 <project xmlns="http://maven.apache.org/POM/4.0.0" x ...

  2. web.xml文件详解

      web.xml文件详解 Table of Contents 1 listener. filter.servlet 加载顺序 2 web.xml文件详解 3 相应元素配置 1 listener. f ...

  3. [转]AndroidManifest.xml文件详解

    转自:http://www.cnblogs.com/greatverve/archive/2012/05/08/AndroidManifest-xml.html AndroidManifest.xml ...

  4. Maven pom.xml文件详解

    Maven pom.xml文件详解 一.简介 POM全称是Project Object Model,即项目对象模型. pom.xml是maven的项目描述文件,它类似与antx的project.xml ...

  5. javaweb web.xml文件详解

    web.xml文件详解 前言:一般的web工程中都会用到web.xml,web.xml主要用来配置,可以方便的开发web工程.web.xml主要用来配置Filter.Listener.Servlet等 ...

  6. tomcat 加载顺序 web.xml文件详解

    一. 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Se ...

  7. AndroidManifest.xml文件详解(uses-permission)

    语法(SYNTAX): <uses-permissionandroid:name="string"/> 被包含于(CONTAINED IN): <manifest ...

  8. Java自动化测试框架-12 - TestNG之xml文件详解篇 (详细教程)

    1.简介 现在这篇,我们来学习TestNG.xml文件,前面我们已经知道,TestNG就是运行这个文件来执行测试用例的.通过本篇,你可以进一步了解到:这个文件是配置测试用例,测试套件.简单来说,利用这 ...

  9. testNG xml文件详解

    网上看到一篇整理的非常详细的xml文件详解,分享一下: 1 <?xml version="1.0" encoding="UTF-8"?> 2 < ...

随机推荐

  1. 让Cocos2D-X的示例程序运行起来

    没有整理好,现在先标记下 安装好环境后可能遇到的问题: 1.cocos2d-X 2.0版本后创建的Android项目提示org.cocos2dx.lib.Cocos2dxActivity找不到问题 解 ...

  2. ac命令根据/var/log/wtmp文件登录退出时间计算用户连接时间

    ac命令根据/var/log/wtmp文件登录退出时间计算用户连接时间

  3. bzoj2014 [Usaco2010 Feb]Chocolate Buying

    Description     贝西和其他奶牛们都喜欢巧克力,所以约翰准备买一些送给她们.奶牛巧克力专卖店里 有N种巧克力,每种巧克力的数量都是无限多的.每头奶牛只喜欢一种巧克力,调查显示, 有Ci头 ...

  4. JIRA官方:JIRA定制工作流

    定制适合项目的工作流 JIRA提供了一个缺省工作流和一系列问题类型,非常适合缺陷追踪和软件开发.在使用中你可以随时根据实际情况对流程进行调整,确保流程能够快速的适应坏境变化. 使你的工作流图形化 使用 ...

  5. javascript中对条件推断语句的优化

    无论写什么程序,平时都会用到条件语句,如:if...else... switch这种语句,来达到对条件的推断. 以下看来一段代码: function abc(test){ if (test == 1) ...

  6. 有一种设计风格叫RESTful

    一 前言 刚看了<RESTful Web APIs中文版>.试读了前两章. 每本书的第一章都是抽象得不得了,是整本书的总结:开篇说基础有点简单,从教你怎么向地址栏输入地址訪问网页開始(某人 ...

  7. linux 内核源代码分析 - 获取数组的大小

    #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 測试程序: #include<stdio.h> #include<stdlib. ...

  8. CSS备忘-1

    CSS 可以通过以下方式添加到HTML中: 内联样式- 在HTML元素中使用"style" 属性 内部样式表 -在HTML文档头部 <head> 区域使用<sty ...

  9. PropertyGrid—默认属性,默认事件,属性默认值

    零.引言 PropertyGrid显示一个对象的属性和事件时,可以设置其默认属性和事件,也就是当你选中对象时,propertyGrid中焦点在哪一个属性或事件上.为对象的属性提供默认值,使Proper ...

  10. js 多媒体audio video

    本文主要简单的介绍一下audio 和 video两个标签的用法 <audio src="music.mp3"></audio> <video src= ...