刚入门magento的开发者容易吧布局和视图给混淆. 本文将看看Magento的Layout/Block的做法, 并告诉您如何将其融入Magento的MVC的世界观。

与许多流行的MVC系统相比,Magento的执行控制器不通过数据对象到视图或在视图对象中设置属性(只有少数例外)。相反,视图组件直接引用系统模型来获得它需要显示的信息。

这样的设计决策的后果之一是,视图分成块和模板。块是PHP对象,模板是包含HTML和PHP(在这里PHP作为模板语言)“原始”的PHP文件(带.phtml扩展名)的组合。每一个块都和一个唯一的模板文件绑定。在模板文件 phtml中,“$this”就是指该模板文件对应的块对象。 
一个简单的例子 
看一个默认的产品模板的文件 
app/design/frontend/base/default/template/catalog/product/list.phtml

你会看到下面的PHP模板代码。 
<?php $_productCollection=$this->getLoadedProductCollection() ?> 
<?php if(!$_productCollection->count()): ?> <div class="note-msg"> 
<?php echo $this->__("There are no products matching the selection.") ?> 
</div> <?php else: ?> 
... 
getLoadedProductCollection method方法可以在改模板的Block的class中找到。Mage_Catalog_Block_Product_List找到如图所示

File: app/code/core/Mage/Catalog/Block/Product/List.php 
... 
public function getLoadedProductCollection() 

    return $this->_getProductCollection(); 

... 
块的_getProductCollection方法实例化模型,并读取它们的数据,其结果返回给模板。 
嵌套块 
Magento 把视图分离成块和模板的真正强大之处在于“getChildHtml”方法。这个方法可以让你实现在块中嵌套块的功能。顶层的块调用第二层的块,然后是第三层……这就是 Magento如何输出 HTML的。

块调用块调用块是如何为您的网页的整个HTML布局中创建的。看看一列布局模板。

File: app/design/frontend/base/default/template/page/one-column.phtml

<!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 class="page-popup <?php echo $this->getBodyClass()?$this->getBodyClass():'' ?>"> 
<?php echo $this->getChildHtml('content') ?> 
<?php echo $this->getChildHtml('before_body_end') ?> 
<?php echo $this->getAbsoluteFooter() ?> 
</body>

模板本身只有11行代码。然而,每次调用$this-> getChildHtml(…)将包含和引入另一个块。使用getChildHtml将依次引入另外一个块的HTML 内容,直到最底层的块。 
Magento布局文件 
到这里,块和模板你大概已经熟悉了,但你可能有以下疑问

Magento 怎么知道在一个页面上要用那些块? 
        Magento 怎么知道哪一个块是顶层块? 
        $this->getChildHtml(…)”里面的参数是什么意思?块的名字吗?

Magento 引入了布局对象(Layout Object)来解决上面的那些问题。布局对象(或者说布局文件)就是一个 XML文件,定义了一个页面包含了哪些块,并且定义了哪个块是顶层块。

上次我们是直接从我们的操作方法中输出内容。这一次,让我们为我们的Hello World模块,一个简单的HTML模板。

首先,创建一个文件: 
app/design/frontend/base/default/layout/local.xml

包含以下内容

<layout version="0.1.0"> 
<default> 
<block type="page/html" name="root" output="toHtml" template="jbw/helloworld/simple_page.phtml" /> 
</default> 
</layout> 
创建模板文件 
app/design/frontend/base/default/template/jbw/helloworld/simple_page.phtml

加入以下内容

<!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 "> 
<head> 
<title>Hello World</title> 
<style type="text/css"> 
body { 
background-color:#f00; 

</style> 
</head> 
<body>

</body> 
</html>

最后,我们要在执行控制器里面调用布局文件,开始输出HTML。我们需要添加两个方法到操作方法。 
public function indexAction() { 
//remove our previous echo 
//echo 'Hello Index!'; 
$this->loadLayout(); 
$this->renderLayout(); 

清空Magento缓存并加载你的Hello World器页面(URL“ http://exmaple.com/helloworld/index/index ”)。现在,你应该可以看到一个明显的红色背景,并且simple_page.phtml的HTML源代码和你打开网站的源码一样。

这是怎么回事呢? 
也许你看到这里一头雾水,没关系,我们来慢慢解释

首先,你要安装一个Layout Viewer模块。这类似于你建的Hello World的文章,可以让我们看一些Magento的内部在Yljtest模块一个模块。

一旦你安装了这个模块(类似于你如何设置Yljtest模块),请访问以下网址

http://example.com/helloworld/index/index?showLayout=page

这是你正在请求页面的布局XML文件,它由<block />, <reference /> 和 <remove />标签组成. 当你调用方法控制器中的loadLayout时, Magento 将

生成布局的XML文件 
        为每一个<block />标签生成一个Block类,查找使用标签的type属性的类作为一个全局性的配置路径,并将其保存在布局对象internal _blocks数组中,使用标签的name属性为数组的key。 
        如果<block />标签包含一个输出属性,它的值将被添加到布局对象的internal _output数组中。

然后,当你在你的动作控制器调用renderLayout方法是,Magento将在_output数组中遍历所有的块,使用输出属性的值作为一个回调方法。这始终是toHtml,以及起点输出将是块的模板。

以下各节将介绍如何块被实例化,这个布局文件是如何产生的,并且完成了输出过程。 
Magento块实例化 
在布局文件中,<block />和<reference />标签有一个“type”属性,这个属性其实是一个 URI 
<block type="page/html" ... 
<block type="page/template_links" ... 
Magento 就是通过这个URI是用来查找块对应的类名。这个 URI分为两部分,第一部分“page”是用来在全局配置中查找一个基本类名,第二部分“html”或者“template_link”将被添加到基本类名后面生成一个具体的将被实例化的类名。

我们以“page/html”为例。首先 Magento在全局配置中找到节点 
global/blocks/page

找到

<page> 
<class>Mage_Page_Block</class> 
</page>

这里我们拿到了一个基本类名“Mage_Page_Block”,然后添加“html”到基本类名后面,我们就得到最终的块对象的类名 
 “Mage_Page_Block_Html”。块的类名在 Magento中被称为(Grouped Class Names),这些类都用相似的方法被实例化。

如果我们创建一个已经存在的且具有相同名称的块的块,新的块实例将取代原来的实例。这时我们的引用(reference)文件从local.xom中。 
<layout version="0.1.0"> 
<default> 
<block type="page/html" name="root" output="toHtml" template="jbw/helloworld/simple_page.phtml" /> 
</default> 
</layout> 
在这里,块“root”被我们用<reference />替换了,指向了一个不同的模板文件。 
references的使用 
<refernce name=”” />将挂钩于一个指定name的xml块中<refernce name=”” />。<block />节点将作为子块来被父块引用。 
<layout version="0.1.0"> 
<default> 
<block type="page/html" name="root" output="toHtml" template="page/2columns-left.phtml"> 
<!-- ... sub blocks ... --> 
</block> 
</default> 
</layout> 
在不同的布局文件: 
<layout version="0.1.0"> 
<default> 
<reference name="root"> 
<!-- ... another sub block ... --> 
<block type="page/someothertype" name="some.other.block.name" template="path/to/some/other/template" /> 
</reference> 
</default> 
</layout> 
尽管root block是在一个单独的XML配置文件中声明,新的block作为子块添加块。 Magento最初创建一个名为root的page/ html块。我们仍然可以用reference来分配新块some.other.block.name来作为root的子块。 
布局文件是如何生成的 
现在我们对布局文件已经有所了解了,但是这个布局文件是那里来的呢?要回答这个问题,我们得引入Magento 中的另外两个概念,句柄(Handle)和包布局(Package Layout)。 
句柄 
Magento 会为每一个页面请求生成几个不同的操作。我们的Layout View模块可以显示这些处理器 
http://example.com/helloworld/index/index?showLayout=handles 
您应该看到(根据你的配置),类似于下面的清单

default 
        STORE_bare_us 
        THEME_frontend_default_default 
        helloworld_index_index 
        customer_logged_out

所有这些是一个句柄。我们可以在 Magento系统的不同的地方配置句柄。这两个我们要注意的是default和helloworld_index_index。“default”句柄是Magento 的 默认句柄,参与每一个请求的处理。 该helloworld_index_index手柄是由路由名称(HelloWorld),动作控制器的名称(index),和动作控制器动作方法(index)组合成一个字符串创建。 这意味着,在动作控制器的每个方法都有它关联的句柄。

请记住,“index”是Magento默认的动作控制器和操作方法,所以下面的请求 
http://example.com/helloworld/?showLayout=handles

同时将产生一个手柄名为helloworld_index_index

包布局 
包布局和我们以前讲过的全局配置有些相似。它是一个巨大的XML 文档包含了Magento 所有的布局配置。我们可以通过以Layout View模块来查看包布局,请求一下 URL 
http://example.com/helloworld/index/index?showLayout=package

这可能需要一段时间来加载。如果您的浏览器呈现XML时卡死了,尝试文本格式(txt) 
http://example.com/helloworld/index/index?showLayout=package&showLayoutFormat=text

你应该可以看到一个非常大的XML文件。这是包布局。这个XML文件是通过结合所有的XML布局文件的内容形成当前的主题(或包)创建的。如果是默认安装,在以下目录 
app/design/frontend/base/default/layout/ 
幕后有<frontend><layout><updates /> 和 <adminhtml><layout><updates />全局配置的区域包含所有文件名的节点加载相应区域。一旦在配置中列出的文件被合并,Magento的合并将在最后一个XML文件中,引用(reference)。在这里,你能够自定义添加到您的Magento安装文件。 
结合句柄和包布局 
所以,如果你看一下包布局,你会看到一些熟悉的标记,如<block /> and <reference />,但他们都被标签包围着,例如 
<default /> 
<catalogsearch_advanced_index /> 
etc... 
这些就是操作标签。对于每个特定的请求来说,针对这个请求的布局文件是由包布局中所有和这个请求相关的操作标签组成的。比如我们上面的例子,和请求相关的操作标签如下 
<default /> 
<STORE_bare_us /> 
<THEME_frontend_default_default /> 
<helloworld_index_index /> 
<customer_logged_out /> 
有一个额外的标签,你需要注意包布局,<update />标签可以让你有另一个句柄的标签。例如 
<customer_account_index> 
<!-- ... --> 
<update handle="customer_account"/> 
<!-- ... --> 
</customer_account_index> 
这段代码的意思是,如果一个请求包含了“customer_acount_index“,那么这个请求的布局文件也应该包含“customer_account”句柄标签

运用我们所学 
好了,理论讲完了。让我们回到我们之前做过的,了解我们现在要做什么,添加 
<layout version="0.1.0"> 
    <default> 
        <block type="page/html" name="root" output="toHtml" template="jbw/helloworld/simple_page.phtml" /> 
    </default> 
</layout>

我们来看 local.xml,我们已经用不同的块覆盖了“root”标签。把这个放在<default />句柄里,这个句柄是我们已经确保了在系统中每一个页面请求将被覆盖。这可能不是我们想要的。

如果你到你的Magento网站任何其他网页,你会发现他们要么空白,或具有相同的红色背景在你的hello world 页面。让我们改变你的文件local.xml,因此只适用于这个Hello World页面。我们将通过改变默认的,而使用完整的动作名称句柄(helloworld_index_index)做到这一点。 
<layout version="0.1.0"> 
<helloworld_index_index> 
<block type="page/html" name="root" output="toHtml" template="jbw/helloworld/simple_page.phtml" /> 
</helloworld_index_index> 
</layout>

清空Magento缓存,并重新请求magento的各个页面,你应该发现都恢复正常了,但是针对”hello world”模块的请求页面还是我们自定义的那个。

眼下这仅适用于我们的index操作方法。让我们把它添加到goodbye动作方法为好。在动作控制器,修改goodbye的动作,如 
public function goodbyeAction() { 
$this->loadLayout(); 
$this->renderLayout(); 

如果加载了下面的URL,你会发现你得到仍然是默认Magento布局。 
http://example.com/helloworld/index/goodbye

We need to add a Handle for the full action name (helloworld_index_goodbye) to our local.xml file. Rather than specify a new <bloxk />, lets use the update tag to include the helloworld_index_index Handle.我们需要添加一个句柄全动作名称(helloworld_index_goodbye)到我们的local.xml文件。而不是指定一个新的<bloxk/>,允许使用更新标记来包含helloworld_index_index手柄。 
<layout version="0.1.0"> 
<!-- ... --> 
<helloworld_index_goodbye> 
<update handle="helloworld_index_index" /> 
</helloworld_index_goodbye> 
</layout>

加载以下页面(清除Magento缓存后)现在应该产生相同的结果。 
http://example.com/helloworld/index/index 
http://example.com/helloworld/index/goodbye 
开始输出和getChildHtml 
In a standard configuration, output starts on the Block named root (because it has an output attribute). We’ve overridden root’s Template with our own在标准配置中,输出开始于名为root块(因为它有一个output输出属性)。我们用我们自己的覆盖root模板 
template="jbw/helloworld/simple_page.phtml"

模板是从当前主题的root文件夹引用的。在这种情况下,这是 
app/design/frontend/base/default

所以我们需要深入到我们的自定义页面。大多数Magento模板存储在 
app/design/frontend/base/default/templates

结合我们的完整路径 
app/design/frontend/base/default/templates/jbw/helloworld/simple_page.phtml

添加内容块 
一个简单的红色的页面是很无聊的。让我们添加一些内容到这个网页。改变你的<helloworld_index_index/>在local.xml文件,所以它看起来像下面的 
<helloworld_index_index> 
<block type="page/html" name="root" output="toHtml" template="jbw/helloworld/simple_page.phtml"> 
<block type="customer/form_register" name="customer_form_register" template="customer/form/register.phtml"/> 
</block> 
</helloworld_index_index>

We’re adding a new Block nested within our root. This is a Block that’s distributed with Magento, and will display a customer registration form. By nesting this Block within our root Block, we’ve made it available to be pulled into our simple_page.html Template. Next, we’ll use the Block’s getChildHtml method in our simple_page.phtml file. Edit simple_page.html so it looks like this

我们增加一个新的模块嵌套在我们的root。这是一个Magento分布式,并会显示客户登记表的block。在我们的root块中嵌套这个block,我们已经将其提放进了我们的simple_page.html模板。接下来,我们将在我们的simple_page.phtml文件中使用块的getChildHtml方法。编辑simple_page.html,所以它看起来是这样的 
<body> 
<?php echo $this->getChildHtml('customer_form_register'); ?> 
</body> 
Clear your Magento cache and reload the page and you should see the customer registration form on your red background. Magento also has a Block named top.links. Let’s try including that. Change your simple_page.html file so it reads清空Magento缓存并刷新页面,你会看到你的红色背景的客户登记表。 Magento的也有一个叫块top.links。让我们尝试包含他。改变你的simple_page.html文件,以便它读取 
<body> 
<h1>Links</h1> 
<?php echo $this->getChildHtml('top.links'); ?> 
</body> 
When you reload the page, you’ll notice that your <h1>Links</h1> title is rendering, but nothing is rendering for top.links. That’s because we didn’t add it to local.xml. The getChildHtml method can only include Blocks that are specified as sub-Blocks in the Layout. This allows Magento to only instantiate the Blocks it needs, and also allows you to set difference Templates for Blocks based on context.当你刷新页面,你会发现,你的<h1>Links</h1>标题显示出来了,但top.links什么都没有显示。这是因为我们没有将它添加到local.xml中。该getChildHtml方法只能包括被指定为子块的布局块。这样Magento只实例化它需要的块,并且还允许您设置不同的模板基于上下文块。

让我们添加top.links到我们的local.xml 
<helloworld_index_index> 
<block type="page/html" name="root" output="toHtml" template="jbw/helloworld/simple_page.phtml"> 
<block type="page/template_links" name="top.links"/> 
<block type="customer/form_register" name="customer_form_register" template="customer/form/register.phtml"/> 
</block> 
</helloworld_index_index> 
清除缓存,并重新加载页面。您现在应该看到top.links模块。 
Time for action 
在我们总结这一刻之前,我们还有一个更重要的概念”覆盖“,那就是<action />标签 ,and that is the <action /> tag. Using the <action /> tag enables us to call public PHP methods of the block classes. So instead of changing the template of the root block by replacing the block instance with our own, we can use a call to setTemplate instead.使用<action />标签,使我们能够调用该块类的公共PHP方法。而不是通过替换我们自己的块实例来更改root块的模板,我们可以用一个调用方法setTemplate来代替。

<layout version="0.1.0"> 
<helloworld_index_index> 
<reference name="root"> 
<action method="setTemplate"> 
<template>jbw/helloworld/simple_page.phtml</template> 
</action> 
<block type="page/template_links" name="top.links"/> 
<block type="customer/form_register" name="customer_form_register" template="customer/form/register.phtml"/> 
</reference> 
</helloworld_index_index> 
</layout>

This layout XML will first set the template property of the root block, and then will add the two blocks we use as child blocks. Once we clear the cache, the result should look just as before. The benefit of using the <action /> is the same block instance is used that was created earlier, and all other parent/child associations still exist. For that reason this is a more upgrade proof way of implementing our changes.这种布局的XML将首先设置root块的模板属性,然后将增加我们的两个子块。一旦我们清除缓存,结果看起来应该像以前一样。使用<action />的好处是同一个块实例可以用前面创建过的,和所有其他的父/子关联仍然存在。出于这个原因,这是我们一个重要的变化升级方式。

All arguments to the action’s method need to be wrapped in an individual child node of the <action /> tag. The name of that node doesn’t matter, only the order of the nodes. We could have written the action node from the previous example as follows with the same effect. 
 该操作的方法的所有参数需要被包裹在<action />标签的单个子节点。该节点的名字也没关系,仅仅是节点的顺序。我们可以写上一示例的具有相同的效果<action />节点如下。 
<action method="setTemplate"> 
<some_new_template>jbw/helloworld/simple_page.phtml</some_new_template> 
</action>

这只是为了说明这一行动的说法,节点名是任意的。

原文链接:http://www.52xiaotu.com/magento-4-layout-block/

Magento开发文档(四)Magento 布局、块 、模板相关推荐

  1. Magento开发文档(七):Magento EAV模型

    在第一篇介绍Magento ORM的文章中,我们提到过Magento拥有两类模型.普通的模型及Entity Attribute Value(EAV)模型.这里首先搞清楚它们之前的一些关系. 所有的Ma ...

  2. Magento开发文档(一):Magento入门

    开始之前,首先声明下,Magento开发者手册由Alan Storm发表在Magento官方网站上.总共分八个部分,由浅入深的介绍了Magento的MVC架构及Magento中使用的比较特殊的EAV模 ...

  3. luajit开发文档wiki中文版(四) LuaJIT 内部结构

    2022年6月10日15:15:22 luajit开发文档中文版(一)下载和安装 luajit开发文档中文版(二)LuaJIT扩展 luajit开发文档中文版(三)FAQ 常见问题 luajit开发文 ...

  4. Android 界面滑动实现---Scroller类 从源码和开发文档中学习(让你的布局动起来)...

    在android学习中,动作交互是软件中重要的一部分,其中的Scroller就是提供了拖动效果的类,在网上,比如说一些Launcher实现滑屏都可以通过这个类去实现..   例子相关博文:Androi ...

  5. NFC开发 —————实用工具以及开发文档(四)

    关于开发NFC必不可少的就是官方开发软件,以及开发文档,这篇文章给大家详细讲解一下,关于官方软件合集<文章末尾有下载地址> Android NFC开发(一) NFC开发 -----实现NF ...

  6. autojs 开发文档集合

    加入我们的QQ群553908361,和各作者同群交流 教程会优先发布于收费脚本v群. 该代码选自于aj开发者的文档,群里有人反馈开发文档打开慢.所以做了这个.方便搜索.如有侵权,请私信我进行删除 同时 ...

  7. 前端开发文档(开发之前个人的准备)

    前言: 前端开发文档,目前自己正在开发的项目之前的个人准备,按照自己的开发习惯来编写,有问题或者不足的地方还望指出,谢谢~ 如有侵权,实属无意,请立即联系,立删. 环境搭建 需要准备的软件 a. No ...

  8. 如何使用融云地图,文件等插件--融云 Android SDK 2.8.0+ Extension 开发文档

    转载自融云 Android SDK 2.8.0+ Extension 开发文档 融云 SDK 2.8.0 后对 会话界面输入区域.+号扩展区域.语音消息.Emoji 等进行了优化和重构,重构后上列区域 ...

  9. M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档

    M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档 分布式基础篇 一.环境搭建 各种开发软件的安装 虚拟机: docker,mysql,redis 主机: Maven, idea(后端),Vs ...

最新文章

  1. java - 第一阶段总结
  2. python 检测四边形,并矫正
  3. java csrf_java使用jsp servlet来防止csrf 攻击的实现方法
  4. 超详细!各种内部排序算法的比较
  5. dubbo源码解析-zookeeper创建节点
  6. python,pytorch:读取,保存,显示图片
  7. AD Framework 单点登录
  8. 【ElasticSearch】Es 源码之 PersistedClusterStateService 源码解读
  9. TensorFlow VGG16
  10. JavaScript学习(七十六)—this的指向问题
  11. SDRAM学习笔记(二)
  12. Django(五):后台管理平台admin
  13. LR9.10破解方法。
  14. _crol_和_cror_的使用
  15. 商城APP开发关键板块
  16. ABAP的OPEN CURSOR语法
  17. Exception:org.eclipse.m2e.wtp.MarkedException: Unable to configure OHBC
  18. 24点游戏java代码 中国开源社区_编程实现一个有GUI的24点游戏
  19. openssl开发库安装时的踩坑指南
  20. Linux 机器重启reboot命令

热门文章

  1. 【uni-app】使用写字板,实现手写签名----直接使用版
  2. [原创]对冒险岛Online配置信息研究的总结
  3. Deep Mutual Learning论文初读
  4. 期货ML策略(一)数据获取
  5. 电子元器件销售如何从小白到精英
  6. php 修改图像大小,PHP中修改图像大小 - PHP - 软件工程|架构设计|网站设计|艺术营销 - 河洛炎黄 - 魏文侯...
  7. 台达plc读取变频器电流案例_DELTA台达VFD-E变频器接线图和接线注意事项
  8. vue项目美食杰 -- 发布菜谱
  9. Clean-label Backdoor Attack against Deep Hashing based Retrieval论文笔记
  10. SpringBoot连接TDengine集群写入超时