简介中我们提到过,布局视图在整个应用中是共享的,它包裹控制器视图。一个布局视图通常包含一些普通的页面元素,例如:头部、底部、导航、内容区(显示视图输出)。布局视图常常被分为独立的子视图。例如,页面头部可能就是一个子视图,全局的导航又是另一个,等等。主视图包含子视图的引用。你可以使用受保护属性$_layout_default
来指定应用的主视图。
下面这张图显示了主视图文件和外部容器、黄色容器及每个子视图的关系。每个容器的定位是通过层叠样式表(CSS)完成的。
外部和黄色区域代表主视图。_head.php
部分是页面源代码的一部分,但是它并不在屏幕上显示。
让我们把第一章创建的博客变成上图的样子。
我们要做的第一件事就是指定博客应用使用哪个布局。记住Acme_App_Blog
应用类继承自Acme_Controller_Page
类。
切换至SYSTEM/source/acme/Acme/Controller
目录,编辑文件Page.php
。
$ cd SYSTEM/source/acme/Acme/Controller/ $ vim Page.php
在类中加入以下代码,就像下面这样:
<?php abstract class Acme_Controller_Page extends Solar_Controller_Page { /** * * Sets up the Acme_App environment. * * @return void * */ protected function _setup() { parent::_setup(); // set the default layout for all applications that // extend Acme_Controller_Page $this->_layout_default = 'blog'; } } ?>
Note | |
---|---|
你也可能通过定义保护属性
|
这里,默认布局是blog.php
,且位于SYSTEM/source/acme/Acme/Controller/Page/Layout
目录。
$ cd SYSTEM/source/acme/Acme/Controller/Page/Layout $ vim blog.php
在默认布局中粘贴以下代码。
<!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"> <?php // generate the <head> include $this->template('_head.php'); ?> <?php // generate the <body> include $this->template('_body.php'); ?> </html>
这是我们的主视图脚本。其中引用了2个子视图,分别是_head.php
和_body.php
。
现在我们要创建子视图_head.php
。假设你仍然在SYSTEM/source/acme/Acme/Controller/Page/Layout
目录下,创建_head.php
文件。
$ vim _head.php
在文件中粘贴以下代码并保存文件。
<head> <?php // use the Solar_View_Head::head() helper // add a base stylesheet, then set any other head elements echo $this->head()->addStyleBase('Acme/Controller/Page/styles/blog.css') ->fetch(); ?> </head>
这个视图脚本负责处理<head></head>
标签的内容。它通过Solar_View_Helper_Head
辅助类设置主样式表及添加其他头部元素。详情请查看Solar_View_Helper_Head辅助类的API文档。
假设你仍然在SYSTEM/source/acme/Acme/Controller/Page/Layout
目录下,创建_body.php
文件。
$ vim _body.php
在文件中粘贴以下代码并保存文件。
<?php // set the id of the body tag. Handy for css and javascript ?> <body id="<?php echo "{$this->controller}-page" ?>"> <div id="wrap"> <div id="header"> <?php include $this->template('_header.php'); ?> </div> <div id="nav"> <?php include $this->template('_nav.php'); ?> </div> <div id="main"> <?php // Add the content from the application controller ?> <?php echo $this->layout_content; ?> </div> <div id="footer"> <?php include $this->template('_footer.php'); ?> </div> </div> </body>
视图脚本定义了页面的结构。层叠样式表定义了每个页面元素的样式。页面的每一个元素,例如页面头部(header),都有自己的子视图脚本。应用程序的控制器动作输出通过$this->layout_content
属性注入到视图中。
假设你仍然在SYSTEM/source/acme/Acme/Controller/Page/Layout
目录下,创建_header.php
文件。
$ vim _header.php
在文件中粘贴以下代码并保存文件。
<div id="branding"> <h1>The Acme Blog</h1> </div>
这个简单的子视图创建了页面顶部的横幅。
现在,仍然在这个目录下创建_footer.php
文件。
$ vim _footer.php
在文件中粘贴以下代码并保存文件。
<div id="footer"> <p>Copyright © 2010 Acme</p> </div>
这个简单的子视图创建了页面底部的页脚。
接下来,我们要创建导航元素。假设你仍然在SYSTEM/source/acme/Acme/Controller/Page/Layout
目录下,创建_nav.php
文件。
$ vim _nav.php
在文件中粘贴以下代码并保存文件。
<div id="nav"> <ul> <li><?php echo $this->action('blog', 'Blog Home'); ?></li> <li><?php echo $this->action('blog/add', 'ACTION_ADD'); ?></li> <li><?php echo $this->action('blog/drafts', 'View Drafts'); ?></li> </ul> <?php // allow for extra local navigation include $this->template('_local.php'); ?> </div>
注意对子视图_local.php
的引用。添加此子视图让我们可以选择性地为每个控制器添加额外的导航。这将在本章后面变得更清晰。
Note | |
---|---|
导航视图中的第二个列表项使用本地键作为链接文字。 <?php echo $this->action('blog/add', 'ACTION_ADD'); ?> 请参考Solar_View_Helper_Action辅助类的API文档和第一章对本地化的介绍。 |
在同一个目录下创建_local.php
文件。
$ vim _local.php
在文件中粘贴以下代码并保存文件。
<?php
// placeholder for local navigation
所有的布局视图都建好了。现在,在SYSTEM/source/acme/Acme/Controller/Page/Layout
目录下应该有这些文件:
Acme/Controller/Page/ Layout/ _body.php _footer.php _head.php _header.php _local.php _nav.php blog.php
Note | |
---|---|
尽管不是必须的,但是以下划线开始命名局部视图、嵌套视图或布局能让你迅速辨别它们。 |
现在你去访问博客应用的话,视觉上肯定会让你很失望。在_head.php
文件中,我们引用了样式表blog.css
。这个样式表负责定位页面元素、设置字体及颜色。我们现在就来创建它。
首先,在SYSTEM/source/acme/Acme/Controller/Page/Public
目录下创建子目录“styles”。
$ cd ../Public $ mkdir styles $ cd styles
接下来,在刚建的目录下创建CSS文件blog.css
。
$ vim blog.css
在文件中粘贴以下代码并保存文件。
body, html { margin: 0; padding: 0; color: #000; background-color: #fff; font-family: sans-serif; font-size: 10pt; } #wrap { width: 750px; margin:0 auto; background-color: #ccc; } #header { background-color: #666; margin: 0px; color: #fff; margin-top: 10px; } #header h1 { margin: 0; padding: 10px; } #nav { background-color: #ccc; width: 150px; float: left; } #main { float: left; width: 580px; background-color: #efefef; padding: 10px; min-height: 400px; } #main h2 { margin-top: 0px; padding-top: 0px; } #footer { background-color: #000; color: #fff; font-weight: bold; clear: both; padding: 5px; } #footer p { padding: 0px; margin: 0px; }
我们刚才做的事如下:
Acme/Controller/Page/ Public/ styles/ blog.css
Note | |
---|---|
|
现在我们来看一下博客的首页(http://localhost/blog),应该和下图一样:
因为布局是共享的,它们极大地减少了代码的重复。但是有时候在某些特殊应用中,你可能想更换页面的某些元素。模块化方式布局和Solar的类栈(类层次)机制使这种任务非常简单。例如,如果我们想在主导航下面创建某个特殊应用的链接,我们只要简单的覆盖_local.php
布局脚本即可。
在SYSTEM/source/acme/Acme/App/Blog/Layout
目录下创建新文件_local.php
。
$ cd SYSTEM/source/acme/Acme/App/Blog/Layout $ vim _local.php
在文件中粘贴以下代码并保存文件。
<ul> <li><a href="#">Local Item One</a></li> <li><a href="#">Local Item Two</a></li> </ul>
现在,刷新浏览器,你将看到左边导航发生了变化。在这里,原先在SYSTEM/source/acme/Acme/Controller/Page/Layout
目录下的_local.php
文件被SYSTEM/source/acme/Acme/App/Blog/Layout
目录下的_local.php
文件覆盖。
Solar使用和应用相关度最大的文件。如果它没有找到它要找的信息,它将会继续在类栈(层次)中向上查找。
下面是一个布局类栈的示例:
Array ( [0] => Acme/App/Blog/Layout [1] => Acme/Controller/Page/Layout [2] => Solar/Controller/Page/Layout )
注意到Acme_App_Blog
继承自Acme_Controller_Page
,而Acme_Controller_Page
又继承自Solar_Controller_Page
。知道这个将帮助你理解Solar的类栈是如何构建的。
Note | |
---|---|
你可以在控制器中设置 |