目录
Zend_View 占位符:介绍
占位符的基本使用
标准占位符
视图标准的小结
Zend_View 占位符:介绍
在前面的一章中,我们主要的看了 Two Step View 模式,它允许你在一个全网站的模板中嵌入独立的应用程序的视图。在那一章的结尾,然而,我们讨论到了一些不足:
- 你如何改变页面标题?
- 你如何把另外的脚本或者风格样式表注入全网站模板中?
- 你如何创建一个横幅以及如何展示它?如果有些内容对于横幅来说是无条件的,有些内容则是有条件的?
这些问题将由 Composite View 来回答。那个模式的一个办法是为全网站模板提供提示或者内容。在 Zend Framework 中,这将通过专门的视图帮助器名叫 占位符 达到。占位符允许你合并内容,然后把合并的内容展示在其它地方。
占位符基本用法
Zend Framework 定义了一个通用的 placeholder() 视图帮助器你可以用来定制你所需要的占位符。它也提供大量专门的经常所需功能的占位符应用,例如指定 DocType 声明,文档的标题,以及更多。
所有的占位符在总体上运行是一致的。他们是容器,这样以便你能把它们当作收集物来执行。使用它们,你可以做到:
- 附加或者预加物体到收集物上
- 用一个单独的值来取代整个收集物。
- 指定一个字符串,当呈现收集物的时候用它来前置输出
- 指定一个字符串,当呈现收集物的时候用它来分割事物
- 把内容采集到收集物中
- 呈现合并的内容
典型的,你不用参数就可以调用这个帮助器,它将返回一个你可以操作的容器。然后你可以输出这个容器来呈现它,或者调用它的方法来配置和填充它。如果容器是空的,呈现它会简单的返回一个空的字符串;否则,内容将会根据你配置的规则被合并。
举例说明,让我们创建一个由一些块内容组成的横幅。你极可能提前知道各个块的结构,让我们假设此例中它看起来是这样的:
-
<div class="sidebar">
-
<div class="block">
-
<p>
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
-
consectetur aliquet odio ac consectetur. Nulla quis eleifend
-
tortor. Pellentesque varius, odio quis bibendum consequat, diam
-
lectus porttitor quam, et aliquet mauris orci eu augue.
-
</p>
-
</div>
-
<div class="block">
-
<ul>
-
<li><a href="/some/target">Link</a></li>
-
<li><a href="/some/target">Link</a></li>
-
</ul>
-
</div>
-
</div>
基于控制器和行为,内容会有所不同,但是结构是一样的。这我们首先为我们的 bootstrap 以一种资源方法来建立横幅。
-
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
-
{
-
// ...
-
-
protected function _initSidebar()
-
{
-
$this->bootstrap('View');
-
$view = $this->getResource('View');
-
-
$view->placeholder('sidebar')
-
// "prefix" -> markup to emit once before all items in collection
-
->setPrefix("<div class=\"sidebar\">\n <div class=\"block\">\n")
-
// "separator" -> markup to emit between items in a collection
-
->setSeparator("</div>\n <div class=\"block\">\n")
-
// "postfix" -> markup to emit once after all items in a collection
-
->setPostfix("</div>\n</div>");
-
}
-
-
// ...
-
}
上面定义了一个占位符,横幅,没有事物。但是它按照我们的要求创建了这个占位符基本的标记结构。
现在,这我们假设全部行为的用户控制器,我们想在顶部出现一个包括一些信息的块。我们可以通过两种方法来完成:(a)我们可以在控制器的 preDispatch() 方法上增加内容,或者(b)我们可以从 preDispatch() 方法内部中呈现一个视图脚本。我们使用(b)计划,因为它遵循一个更多合适的注意力分离(把和视图相关的逻辑和功能留在一个视图脚本内)。
我们会这个视图脚本命名为 user/_sidebar.phtml,用以下内容填满它:
-
<?php $this->placeholder('sidebar')->captureStart() ?>
-
<h4>User Administration</h4>
-
<ul>
-
<li><a href="<?php $this->url(array('action' => 'list')) ?>">
-
List</a></li>
-
<li><a href="<?php $this->url(array('action' => 'create')) ?>">
-
Create</a></a></li>
-
</ul>
-
<?php $this->placeholder('sidebar')->captureEnd() ?>
以上的例子使用了占位符的内容采集功能。默认的,内容被当作一个新事物附加到容器内,让我们合并内容。这个例子为了创建标记,使用了视图帮助器和静态 HTML,内容然后被采集然后附加进占位符本身。
为了唤醒以上视图脚本,我们要把以下内容写进我们的 preDispatch() 方法中:
-
class UserController extends Zend_Controller_Action
-
{
-
// ...
-
-
public function preDispatch()
-
{
-
// ...
-
-
$this->view->render('user/_sidebar.phtml');
-
-
// ...
-
}
-
-
// ...
-
}
注意我们没有采集被呈现的值,这没有必要,因为那个视图整个正在被采集进一个占位符内。
现在,让我们假设我们的在同一个控件器中的 视图 行为需要呈现一些信息。在 user/view.phtml 视图脚本中,我们可能有以下的代码片断:
-
$this->placeholder('sidebar')
-
->append('<p>User: ' . $this->escape($this->username) . '</p>');
这个例子使用了 append() 方法,把一些简单的标记传递给它来合并。
最后,让我们修改我们的模板视图,并让它呈现占位符:
-
<html>
-
<head>
-
<title>My Site</title>
-
</head>
-
<body>
-
<div class="content">
-
</div>
-
</body>
-
</html>
对于没有被横幅占位符填充的控制器和行为而言,不会输出内容,而对于被填充的而言,然而,输出占位符将会按照我们在 bootstrap 中制定的规则,我们在整个应用程序内合并的内容来呈现内容。对于 /user/view 行为这个个案,个假设一个用户名为 matthew,我们将按照以下来获得横幅的内容(为了易于阅读,已经做了格式化):
-
<div class="sidebar">
-
<div class="block">
-
<h4>User Administration</h4>
-
<ul>
-
<li><a href="/user/list">List</a></li>
-
<li><a href="/user/create">Create</a></a></li>
-
</ul>
-
</div>
-
<div class="block">
-
<p>User: matthew</p>
-
</div>
-
</div>
通过结合占位符和模板脚本,你可以做大量的事情;尝试它们,阅读相关章节来获取更多信息。
标准占位符
在前面的一节中,我们学习了关于 placeholder() 视图帮助器,以及如何使用它来合并定制的内容。在本节中,我们会研究一下 Zend Framework 内置的占位符,以及如何使用它们来创建更复杂的复合模板。
大部分的内置占位符是为了在你的模板内容中的 部分产生内容——一个你不能通过你的应用程序的视图脚本直接操作的区域,但是它是你想施加影响的。举例来说:你可能希望每一个页面的标题包含一定的内容,但是这些内容是基于控制器和/或行为的;你可能希望基于你所在的应用程序的不同的部分来指定 CSS 文件;你可能需要在不同的时间载入不同的 JavaScript 脚本;或者你希望设置 DocType 声明。
Zend Framework 为这些情形内置了占位符,甚至更多。
设置 DocType
DocType 声明要想记住是很麻烦的,同时,它被包括进你的文档以确保浏览器正确呈现你的内容是最基本的。doctype() 视图帮助器允许你使用简单的字符串记忆术来指定希望的 DocType;另外,其它的帮助器将会查询 doctype() 帮助器来确保输出和被请求的 DocType 一致。
举一个例子,如果你想使用 XHTML1 Strict DTD,你可以简单的指定:
$this->doctype('XHTML1_STRICT');
在可选的记忆短语中,你会找到这些常用的类型:
XHTML1_STRICT
XHTML 1.0 Strict
XHTML1_TRANSITIONAL
XHTML 1.0 Transitional
HTML4_STRICT
HTML 4.01 Strict
HTML4_Loose
HTML 4.01 Loose
HTML5
HTML 5
你可以赋值给类型然后在一个单独的调用中呈现声明:
echo $this->doctype('XHTML1_STRICT');
然而,更好的办法是在你的 bootstrap 里面指定类型,然后在你的模板中呈现它。试着把以下添加到你的 bootstrap 类中:
-
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
-
{
-
protected function _initDocType()
-
{
-
$this->bootstrap('View');
-
$view = $this->getResource('View');
-
$view->doctype('XHTML1_STRICT');
-
}
-
}
然后,在你的模板脚本中,在文件的顶部简单的输出帮助器就可以了:
-
<html>
-
<!-- ... -->
这将确保你的关注 DocType 的视图帮助器呈现合适的标记,确保模板在呈现之前设置好类型,同时提供了一个单独改变 DocType 类型的地方
指定页面标题
经常,一个网站会把网站名字或者公司名字包括在页面标题内,然后基于所处网站内的位置再添加额外的信息。举例来说,zend.com 网站所有页面的标题都包含有 Zend.com 这个字符串,在它之前添加基于页面的信息:Zend Server – Zend.com。在 Zend Framework 内部,headTitle() 视图帮助器可以帮助简化这个工作。
最简单的,headTitle() 帮助器允许你为 >title< 标签合并内容;当你输出它,它然后收集基于片断被添加的顺序的信息。你可以使用 prepend() 和 append() 来控制顺序,使用 setSeparator() 方法来为各个片断之间提供一个分割符。
典型的,你应该在你的 bootstrap 中指定对于所有页面都适用的片断,和我们如何定义 doctype 是一样的。在这个例子中,我们会定义一个 _initPlaceholders() 方法来操作许多的占位符,然后指定一个初始的标题和一个分割符。
-
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
-
{
-
// ...
-
-
protected function _initPlaceholders ( )
-
{
-
$this-> bootstrap ( 'View' );
-
$view = $this-> getResource ( 'View' );
-
$view-> doctype ( 'XHTML1_STRICT' );
-
-
// Set the initial title and separator:
-
$view-> headTitle ( 'My Site' )
-
-> setSeparator ( ' :: ' );
-
}
-
-
// ...
-
}
-
<html>
-
<!-- ... -->
-
<!-- If append() was used: -->
-
<title>My Site :: Some Page</title>
-
-
<!-- If prepend() was used: -->
-
<title>Some Page :: My Site</title>
之后,在一个控制器或者特定行为的视图脚本中,我们可以添加更多的风格样式
-
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
-
{
-
// ...
-
-
protected function _initPlaceholders ( )
-
{
-
$this-> bootstrap ( 'View' );
-
$view = $this-> getResource ( 'View' );
-
$view-> doctype ( 'XHTML1_STRICT' );
-
-
// Set the initial title and separator:
-
$view-> headTitle ( 'My Site' )
-
-> setSeparator ( ' :: ' );
-
-
// Set the initial stylesheet:
-
$view-> headLink ( )-> prependStylesheet ( '/styles/site.css' );