magento的布局文件之谜

magento的布局文件layout.xml文件详解

解析顺序

布局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类。

Php代码  

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

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

Php代码  

  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相关文件。

Php代码  

  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.页面头部:主要包括一些头部链接、语言切换等

Php代码  

  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数据块,然后再继续解析它所包含的其他内容。

Php代码  

  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中对应的函数等。

Php代码  

  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中的内容进行翻译成对应的本地化文字。

附:

Php代码  

  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五种。

Php代码  

  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所对应的类中所支持的函数。

Php代码  

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

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

布局原理解析

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.magentobbs.com/index.php?q=content/%E5%B8%83%E5%B1%80%E5%8E%9F%E7%90%86%E8%A7%A3%E6%9E%90%EF%BC%88anatomy-layout%EF%BC%89

magento的布局文件之谜

时间: 2024-10-07 12:06:13

magento的布局文件之谜的相关文章

对另一个布局文件里的Button按钮进行监听

布局文件里面的Button写上 onClick = “onClick”,然后在你当前Activity的onClick方法中根据Button的id来做相应的操作 android:id="@+id/single_file_download" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" androi

【Android】Android Layout Binder——根据layout布局文件自动生成findViewById的java代码的神器

Android Layout Binder是一个网站,能够在线的根据layout布局文件自动生成findViewById的java代码. 网址是http://android.lineten.net/layout.php 如图:

Android布局文件经验

1.父控件中含有多个子控件时,往往遵循长子优先的原则,即长子如果很大可能占满父空间,使次子们出局: 2.假设TableLayout有2行,其中一行未设定列间长度比例,而另一行设定了,则未设定行可能也会遵循设定行的列间长度比例: 3.在某个区域(如TableLayout中某个单元格)显示某张超大的图片,希望图片总是自适应单元格而不是把单元格撑爆.解决方案:将单元格放在LinearLayout中,给LinearLayout设置android:layout_width="wrap_content&qu

Android 多个界面复用一个布局文件

1.layout_common.xml 复用的布局文件 <?xml version="1.0" encoding="utf-8"?> <!-- 复用的布局文件 --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android

eclipse创建android项目无法正常预览布局文件

eclipse创建android项目时,预览layout.xml文件时提示: This version of the rendering library is more recent than your version of ADT plug-in. Please update ADT plug-in,导致无法正常预览布局文件.问题根源:SDK版本过高,ADT版本过低.解决方法如下. 工具/原料 eclipse ADT插件 方法/步骤 1 找到eclipse文件夹,打开eclipse软件,创建a

Android的布局文件遇到Exception raised during rendering: java.lang.System.arraycopy([CI[CII)V问题

打开xml的布局文件,发现布局无法显示预览,而且报错:Exception raised during rendering: java.lang.System.arraycopy([CI[CII)V.原来是因为用了最新的API 20.这个是Android用于开发可穿戴设备的,不支持EditText.将API改为20之前的就行了.

获取联系人【自己定义布局文件与主布局文件相连,数据库内容查找并显示】

一.自己定义布局文件list_item_users.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_

自定义ListView适配器Adapter引用布局文件的情况下实现点击列表项时背景颜色为灰色

listview控件设置适配器的时候,如果使用自定义的adapter,比如MyArrayAdapter extends ArrayAdapter<String> 如果listitem布局文件不做任何处理的话,点击列表项的时候不会出现背景色灰色的现象. 实现思路是:在listitem布局文件中为该布局文件中的父控件:LinearLayout,设置android:background="@drawable/listitemclickseletor" 其中listitemclic

使用布局文件(Layout)

布局文件类似于web form中的母版页,定义一个布局文件,然后在需要使用的视图中指定使用的布局文件,视图会把当前的动态绑定的数据传递到布局文件中,布局文件中也可以访问到这些数据.渲染视图文件中的数据在布局文件中必须使用@RenderBody()方法进行渲染,如果要使用视图文件中的数据就可以使用:@ViewBag.Title来访问视图文件中的数据. Index.cshtml @{ Layout = "~/Views/Shared/_SiteLayout.cshtml";//声明使用的布