第三章 – Magento的布局(Layout),块(Block)和模板(Template)2

时间:2021-10-29 17:20:07

block和reference的区别

我们上面提到block和reference都会实例化块对象,那么它们究竟有什么区别呢? reference在布局文件中是用来表示替换一个已经存在的块,举个例子

<block type="page/html" name="root" output="toHtml" template="page/2columns-left.phtml">
<!-- ... sub blocks ... -->
</block>
<!-- ... -->
<reference name="root">
<block type="page/someothertype" name="root" template="path/to/some/other/template" />
<!-- ... sub blocks ... -->
</reference>

Magento首先创建了一个名叫“root”的块。然后,它有发现了一个引用(reference)的名字也叫“root”,Magento会把原来那个“root”块替换成reference标签里面的那个快。

再来看看我们之前创建那个local.xml

<layout
version
="0.1.0"
>


<default>



<reference
name
="root"
>


<block
type
="page/html"
name
="root"
output
="toHtml"
template
="helloworld/simple_page.phtml"
/>


</reference>



</default>



</layout>



在这里,块“root”被我们用reference替换了,指向了一个不同的模板文件。

布局文件是如何生成的

现在我们对布局文件已经有所了解了,但是这个布局文件是那里来的呢?要回答这个问题,我们得引入Magento中的另外两个概念,操作(Handle)和包布局(Package Layout)。

操作

Magento会为每一个页面请求生成几个不同的操作。我们的Layout View模块可以显示这些处理器

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

你应该看到类似如下列表的列表(和你的配置有关)

Handles For This Request
1. default
2. STORE_default
3. THEME_frontend_default_gap
4. helloworld_index_index
5. customer_logged_out

它们每一个都是一个操作的名字。我们可以在Magento系统的不同的地方配置操作。在这里我们需要关注两个操作 “default” 和 “helloworld_index_index”。“default”处理器是Magento的默认处理器,参与每一个请求的处理。 “helloworld_index_index”处理器的名字是frontname “helloworld”加上执行控制器的名字“index”再加上执行方法的名字“index”。这说明执行控制器的每一个执行方法都有一个相应的操 作。

我们说过“index”是Magento默认的执行控制器和执行方法的名字,所以以下请求的操作名字也是“helloworld_index_index”。

http://example.com/helloworld/?showLayout=handles

包布局

包布局和我们以前讲过的全局配置有些相似。它是一个巨大的XML文档包含了Magento所有的布局配置。我们可以通过以Layout View模块来查看包布局,请求一下URL

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

你可能要等一会儿才能看到输出,因为文件很大。如果你的浏览器在渲染XML的时候卡死了,建议你换成text格式的

http://example.com/helloworld/index/index?showLayout=package&amp;showLayoutFormat=text

假设你选择的是XML格式输出,那么你应该看到一个巨大的XML文件,这就是包布局。这个文件是Magento动态生成的,合并当前主题(theme)下面所有的布局文件。如果你用的是默认安装的话,这些布局文件在以下目录

app/design/frontend/base/default/layout/

其实在全局配置中,有一个updates节点下面定义了所有将被装载的布局文件

<layout>
<updates>
<core>
<file>core.xml</file>
</core>
<page>
<file>page.xml</file>
</page>
...
</updates>
</layout>

当这些文件被装载以后,Magento还会装载最后一个布局文件,helloworld.xml,也就是我们之前新建的那个文件。我们可以通过这个文件来定制Magento的布局。

结合操作和包布局

在包布局文件中,我们可以看到一些熟悉的标签block,reference等等,但是他们都包含在一下这些标签中

<default
/>


<catalogsearch_advanced_index
/>


etc...

这些就是操作标签。对于每个特定的请求来说,针对这个请求的布局文件是由包布局中所有和这个请求相关的操作标签组成的。比如我们上面的例子,和请求相关的操作标签如下

<default />
<store_bare_us />
<theme_frontend_default_default />
<helloworld_index_index />
<customer_logged_out />

所以,针对请求

http://example.com/helloworld/index/index

布局文件就是包布局中上面这些标签的内容组合。在包布局文件中,还有一个标签值得我们注意。我们可以通过这个标签引入另外一个操作标签。比如

<customer_account_index>



<!-- ... -->

<update
handle
="customer_account"
/>


!-- ... -->
</customer_account_index>



这段代码的意思是,如果一个请求包含了“customer_acount_index”操作,那么这个请求的布局文件也应该包含“customer_account”操作标签下面的block和reference。

更新我们的例子

好了,理论讲完了,让我们来修改我们的例子,把这一章的内容实践一下。我们重新来看local.xml

<layout version="0.1.0">
<default>
<reference name="root">
<block type="page/html" name="root" output="toHtml" template="helloworld/simple_page.phtml" />
</reference>
</default>
</layout>

我们用一个引用(reference)覆盖了名为“root”的块。然后定义了一个新的块,指向了一个不同的模板文件。我们把这个引用放在default 操作标签下面,那就说明这个Layout将对所有的请求有效。如果你访问Magento自带的一些页面,你会发现它们要么是空白,要么就是和我们 “hello world”例子的红色背景,但这并不是我们想要的效果。我们来修改一下local.xml,让我们的模板仅对“helloworld”的请求有效。

<layout version="0.1.0">
<helloworld_index_index>
<reference name="root">
<block type="page/html" name="root" output="toHtml" template="helloworld/simple_page.phtml" />
</reference>
</helloworld_index_index>
</layout>

我们把操作标签换成了“helloworld_index_index”。清空Magento缓存,重新访问Magento的各个页面,你应该发现都恢复了正常,但是针对”hello world”模块的请求页面还是我们自定义的那个。

目前我们只实现了一个“index”执行函数,现在我们来实现“goodbye”执行函数。修改我们的执行控制器代码如下

public
function
goodbyeAction(
)
{

$this
->
loadLayout
(
)
;

$this
->
renderLayout
(
)
;

}

但是你访问一下页面的时候你还是会看到Magento的默认布局

http://example.com/helloworld/index/goodbye

那是因为我们没有为这个请求定义布局。我们需要在local.xml中添加“helloworld_index_goodbye”标签。由于“index”请求和“goodbye”请求我们要套用的布局是一样的,所以我们将用标签来重用已有的配置

<layout
version
="0.1.0"
>


<!-- ... -->

<helloworld_index_goodbye>



<update
handle
="helloworld_index_index"
/>


</helloworld_index_goodbye>



</layout>



清空Magento缓存,请求以下URL

http://example.com/helloworld/index/index
http://example.com/helloworld/index/goodbye

你将会得到两个完全相同的页面。

开始输出和getChildHtml方法

在Magento默认的配置下,HTML输出是从名为“root”的块开始(其实是因为这个块拥有output属性【注:任何一个拥有output 属性的块都是顶层块,在拥有多个顶层块的情况下Magento将按照块定义的先后顺序输出HTML】)。我们覆盖了“root”块的模板

template="helloworld/simple_page.phtml"

模板文件的查找路径是当前主题(theme)的根目录,Magento默认设置时这里

app/design/frontend/base/default

为页面加入内容

到目前为止,我们的页面都比较无聊,啥也没有。我们来为页面加点有意义的内容。修改local.xml如下

<helloworld_index_index>



<reference
name
="root"
>


<block
type
="page/html"
name
="root"
template
="helloworld/simple_page.phtml"
>


<block
type
="customer/form_register"
name
="customer_form_register"
template
="customer/form/register.phtml"
/>


</block>



</reference>



</helloworld_index_index>



我们在“root”块里面嵌套了一个块“customer_form_register”。这个块是Magento本来就有的,包含了一张用户注册表单。 我们把这个块嵌套进来,那么我们在模板文件里面就能用这个块的内容。使用方法如下,修改simple_page.phtml

<body>
<?php
echo
$this
->
getChildHtml
(
'customer_form_register'
)
;
?>

</body>

这里“getChildHtml”的参数就是要引入的块的名字,使用起来相当方便。清空Magento缓存,刷新hello world页面,你应该在红色背景上看到用户注册表单。Magento还有一个块,叫做“top.links”,让我们把它也加进来。修改 simple_page.html

         <body>
<h1>Links</h1>
< ?php echo $this->getChildHtml('top.links'); ?>
< ?php echo $this->getChildHtml('customer_form_register'); ?>
</body>

刷新页面,你会发现Links显示出来了,但是“top.links”什么都没有显示。那是因为我们并没有把这个块引入到local.xml,所以 Magento找不到这个块。“getChildHtml”的参数一定要是当前页面的布局文件中声明过的块。这样的话Magento就可以只实例化需要用 到的块,节省了资源,我们也可以根据需要为块设置不同的模板文件。

我们修改helloworld.xml文件如下

<?xml version="1.0" encoding="UTF-8"?>
<layout version="0.1.0">
<helloworld_index_index>
<reference name="root">
<block type="page/html" name="root" output="toHtml" template="helloworld/simple_page.phtml">
<block type="customer/form_register" name="customer_form_register" template="customer/form/register.phtml"/>
<block type="page/template_links" name="top.links"/>
</block>
</reference>
</helloworld_index_index>
</layout>

清空Magento缓存,刷新页面,你会看到一排链接显示出来了。【注:如果你细心一点的话你会发现“top.links”块没有template属性,那是因为这个块的类中一定定义了默认的模板

protected function
_construct(
)

{

$this
->
setTemplate
(
'page/template/links.phtml'
)
;

}


总结

这一章我们讲解了布局的基础知识。你可能会觉得这个很复杂,但是你也不必过分担心,因为平常使用Magento是不会用到这些知识 的,Magento提供的默认布局应该可以满足大部分需求。对于想要深入研究Magento的开发者来说,理解Magento的布局是至关重要的。布局, 块和模板构成了Magento MVC架构中的View,这也是Magento的特色之一。


来自: http://hi.baidu.com/190420456/blog/item/daec9f89be90599ba5c2720d.html