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

我们接着研究Magento。根据我们第二章讲的Magento MVC的架构,我们接下来应该讲模型(Model),但是我们跳过模型先来看布局和块。和一些流行的PHP MVC架构不同的是,Magento的执行控制器不直接将数据传给试图,相反的视图将直接引用模型,从模型取数据。这样的设计就导致了视图被拆分成两部 分,块(Block)和模板(Template)。块是PHP对象,而模板是原始PHP文件,混合了XHTML和PHP代码(也就是把PHP作为模板语言 来使用了)。每一个块都和一个唯一的模板文件绑定。在模板文件phtml中,“$this”就是指该模板文件对应的快对象。

让我们来看一个例子

File: app/design/frontend/base/default/template/catalog/product/list.phtml

你将看到如下代码

<?php
 $_productCollection
=
$this
->
getLoadedProductCollection
(
)
 ?>

<?php if ( ! $_productCollection -> count ( ) ) : ?>
<p class="note-msg"><?php echo $this -> __( 'There are no products matching the selection.' ) ?> </p>
<?php else : ?>

这里“getLoadedProductCollection”方法可以在这个模板的块对象“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的。让我们来看一下单列的顶层模板

File: app/design/frontend/base/default/template/page/1column.phtm

 

<?php

/**
* Template for Mage_Page_Block_Html
*/

?>
<!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 col1-layout">
<div class="main">
<?php echo $this -> getChildHtml ( 'breadcrumbs' ) ?>
<div class="col-main">
<?php echo $this -> getChildHtml ( 'global_messages' ) ?>
<?php echo $this -> getChildHtml ( 'content' ) ?>
</div>
</div>
</div>
<?php echo $this -> getChildHtml ( 'footer' ) ?>
<?php echo $this -> getChildHtml ( 'before_body_end' ) ?>
</div>
</div>
<?php echo $this -> getAbsoluteFooter ( ) ?>
</body>
</html>

我们可以看到这个模板里面很多地调用了“$this->getChildHtml(…)”。每次调用都会引入另外一个块的HTML内容,直到最底层的块。

布局对象

看到这里,你可能有这样的疑问
Magento怎么知道在一个页面上要用那些块?
Magento怎么知道哪一个块是顶层块?
“$this->getChildHtml(…)”里面的参数是什么意思?块的名字吗?
Magento引入了布局对象(Layout Object)来解决上面的那些问题。布局对象(或者说布局文件)就是一个XML文件,定义了一个页面包含了哪些块,并且定义了哪个块是顶层块。

在第二章的时候我们在执行方法(Action Method)里面直接输出了HTML内容。现在我们要为我们的Hello World模块创建一个简单的HTML模板。首先我们要创建如下文件

app/design/frontend/default/default/layout/local.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" />
</reference>
</helloworld_index_index>
</layout>

再创建如下文件

app/design/frontend/default/default/template/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>Untitled</title>
<style type="text/css">
body {
background-color:#f00;
}
</style>
</head>
<body>
<h4>Links</h4>
<?php echo $this -> getChildHtml ( 'top.links' ) ; ?>
<?php echo $this -> getChildHtml ( 'customer_form_register' ) ; ?>
</body>
</html>

最后,我们要在执行控制器里面调用布局文件,开始输出HTML。修改执行方法如下

public
 function
 indexAction(
)
 {

//remove our previous echo
//echo 'Hello Index!';
$this -> loadLayout ( ) ;
$this -> renderLayout ( ) ;
}

清空Magento缓存,访问URL “http://exmaple.com/helloworld/index/index”。你应该看到一个纯红色背景的页面。这个页面的源代码应该和我们创建的文件“simple_page.phtml”一模一样。

究竟是怎么回事呢?

也许你看到这里一头雾水,没关系,我们来慢慢解释。首先你得安装一个 Layout Viewer 模块,这和我们第一章讲的 Config Viewer 模块很相似,都是查看Magento的内部信息。安装完这个模块之后【注:你需要参照第一章的内容,为这个模块创建“app/etc/modules/App_Layoutviewer.xml”】,打开如下URL

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

你看到的是你正在请求的页面的布局文件。它是由block,reference和remove组成的。当你在执行方法中调用“loadLayout”时,Magento会做如下处理
生成这个布局文件
为每一个block和reference标签实例化一个块对象。块对象的类名是通过标签的name属性来查找的。这些块对象被存储在布局对象的_blocks数组中
如果block标签包含了output属性,那么这个块的名字和output属性的值会被添加到布局对象的_output数组中
然后,当你在执行方法中调用“renderLayout”方法时,Magento会遍历_output数组中所有的块名字,从_blocks数组中获得该 名字的块,并调用块对象中使用output属性的值作为名字的函数。这个函数往往是“toHtml”。这个output属性也告诉Magento这里就是 输出HTML的起点,也就是顶层块。【注:直接阅读Layout类的代码应该比较容易理解这里的逻辑

File
:
 app/
code/
core/
Mage/
Core/
Model/
Layout.
php
public function getOutput( )
{
$out = '' ;
if ( ! empty ( $this -> _output) ) {
foreach ( $this -> _output as $callback ) {
$out .= $this -> getBlock ( $callback [ 0 ] ) -> $callback [ 1 ] ( ) ;
}
}
return $out ;
}

从这里我们也可以看出,一个页面的布局文件可以拥有多个顶层块。】

下面我们要讲解块对象是如何被实例化的,这个布局文件时如何被生成的,最后我们将动手做一个例子来实践这一章讲的内容。

实例化块对象

在布局文件中,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”,然后添加URI的第二部分“html”到基本类名后面,我们就得到最终的块对象的 类名 “Mage_Page_Block_Html”。块的类名在Magento中被称为“分组类名”(Grouped Class Names),这些类都用相似的方法被实例化。我们将在以后的章节中详细介绍这个概念。

来自: http://hi.baidu.com/190420456/blog/item/2fa0803c2a61e5c89e3d620c.html
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值