第07章深入视图层.docx
- 文档编号:18372459
- 上传时间:2023-08-16
- 格式:DOCX
- 页数:35
- 大小:47.48KB
第07章深入视图层.docx
《第07章深入视图层.docx》由会员分享,可在线阅读,更多相关《第07章深入视图层.docx(35页珍藏版)》请在冰点文库上搜索。
第07章深入视图层
第7章深入视图层
视图(view)的作用是显示特定动作(action)的输出。
在symfony里,视图由几部分组成,这些部分都很容易修改。
∙Web设计师通常会与模板(当前动作的数据的表现形式)和布局(包含所有页面都会用到的代码)打交道。
这些模板由HTML加上PHP代码片段(主要是辅助函数调用)组成。
∙为了重用,开发者往往会把模板代码的片段放在局部模板(Partials)或者组件(Components)里。
开发者使用槽(Slots)与组件(Components)来影响布局的多个区域。
web设计师也可以修改这些模板片段。
∙开发者专注于YAML视图配置文件(用来设置回应与其他界面元素的属性)还有回应对象(responseobject)。
处理模板里的变量的时候,跨站脚本(corss-sitescripting)的风险不可忽略,这就需要在记录用户数据的时候很好的理解输出转义(outputescaping)技术。
不论你是哪一个角色,你都可以发现能加快输出动作结果这件乏味的工作的工具。
这一章将会介绍这些工具。
模板
例7-1是一个典型的symfony模板。
它包含一些HTML代码和一些基本的PHP代码,通常是显示动作(action)里定义的(通过$this->name='foo';)变量还有辅助函数。
例7-1-indexSuccess.php模板样本
欢迎
欢迎回来
phpecho$name?
>!
- 您要做什么?
phpecholink_to('阅读最新的文章','article/read')?
>
phpecholink_to('写一篇新文章','article/write')?
>
在第4章里介绍过,这种另类的PHP语法对非PHP开发者来说也很容易理解因此很适合于用在模板里。
请注意在模板里面尽量减少PHP代码量,由于这些文件用来设计程序的界面,这些模板有些时候是由其他的团队维护的,例如表现团队而不是应用程序逻辑团队。
把逻辑放在动作(action)里还可以使一个动作对应多个模板更容易,减少代码重复。
辅助函数(Helpers)
辅助函数是返回模板里使用的HTML代码的PHP函数。
在例7-1里,link_to()函数就是一个辅助函数。
有时,辅助函数只是用来节约时间,把模板里常用的代码封装起来。
例如,你很容易想得到下面这个辅助函数的定义:
phpechoinput_tag('nickname')?
>
=>
它应该与例7-2中的差不多。
例7-2-辅助函数定义的例子
functioninput_tag($name,$value=null)
{
return'
}
事实上,symfony内建的input_tag()函数比这个要复杂一点,它有第三个参数,这个参数用来指定标签的属性。
你可以去在线API文档查看这个函数详细的语法与参数。
(http:
//www.symfony-
大多数时候,辅助函数更聪明并且节省大量写代码的时间:
phpechoauto_link_text('请访问我们的网站')?
>
=>请访问我们的网站
辅助函数能加快写模板的速度,同时辅助函数生成的HTML兼具性能与可访问性。
当然,你还是可以写普通HTML代码,不过辅助函数写起来总是要快一些。
TIP你可能会问为什么辅助函数的命名用下划线而不是symfony里随处可见的大小写字母规则。
这是因为辅助函数是函数,所有的PHP核心函数都用下划线命名规则。
声明辅助函数
包含辅助函数定义的symfony文件不能被自动载入(因为它们是函数而不是类)。
辅助函数按照目的分组。
例如,所有处理文字的辅助函数都在一个名叫TextHelper.php的文件里定义,称作Text辅助函数组。
所以如果你要在模板里使用一个辅助函数,你必须在使用之前通过user_helper()函数声明载入这个辅助函数相关的辅助函数组。
例7-3里的这个模板使用了auto_link_text()辅助函数,它属于Text辅助函数组。
例7-3-声名使用一个辅助函数
//在这个模板里使用一个特定的辅助函数
phpechouse_helper('Text')?
>
...
描述
phpechoauto_link_text($description)?
>
TIP如果你要声明多个辅助函数组,给use_helper()函数传多个参数就可以了。
例如,要在一个模板里载入Text和Javascript辅助函数组,可以使用
phpechouse_helper('Text','Javascript')?
>来声明。
有一些辅助函数在所有的模板里都可以使用,不需要事先声明。
它们是以下的辅助函数组:
∙Helper:
用来载入辅助函数(use_helper()函数本身就是一个辅助函数)
∙Tag:
基本的标签辅助函数,几乎所有的辅助函数都用到它
∙Url:
链接与URL管理辅助函数
∙Asset:
用来生成HTML
部分的内容,还包括简化使用外部资源(图片,Javascript,样式表)的函数∙Partial:
用来调用局部模板的辅助函数
∙Cache:
管理代码片段的缓存
∙Form:
表单辅助函数
这里列出的标准辅助函数,在每个模板中都会被自动载入,可以在settings.yml文件里面设置。
所以如果你确定你不会用到Cache辅助函数组的辅助函数,或者你每次都需要用到Text组,你可以修改standard_helper这个设置。
这会稍稍加快你的程序。
但是你不能删除这个列表里的前四个辅助函数组(Helper、Tag、Url和Asset),因为模板引擎需要它们才能正常工作。
所以在标准辅助函数设置(standard_helper)里找不到这四个辅助函数组。
TIP如果你需要在模板之外使用辅助函数,你也可以通过sfLoader:
:
loadHelper($helpers)来载入一个辅助函数组,$helpers可以是辅助函数组的名字或几个辅助函数组名字组成的数组。
例如,如果你想在一个动作(action)里使用auto_link_text(),你需要首先执行sfLoader:
:
loadHelper('Text')。
常用辅助函数
在本节里你会了解一些后面要用到的辅助函数的详情。
例7-4给出了一个常用辅助函数列表,还有它们输出的HTML代码。
例7-4-常用的默认辅助函数
//Helper组
phpechouse_helper('HelperName')?
>
phpechouse_helper('HelperName1','HelperName2','HelperName3')?
>
//Tag组
phpechotag('input',array('name'=>'foo','type'=>'text'))?
>
phpechotag('input','name=footype=text')?
>//另一种选项格式
=>
phpechocontent_tag('textarea','dummycontent','name=foo')?
>
=>
//Url组
phpecholink_to('点我','mymodule/myaction')?
>
=>
//Asset组
phpechoimage_tag('myimage','alt=foosize=200x100')?
>
=>
phpechojavascript_include_tag('myscript')?
>
=>
phpechostylesheet_tag('style')?
>
=>
symfony里还有很多其他的辅助函数,如果要讲完它们需要一整本书。
辅助函数的最佳参考是在线API文档(http:
//www.symfony-所有的辅助函数都有详细的介绍,包括语法,参数,还有例子。
自己写辅助函数
symfony本身包含了大量的各类辅助函数,不过如果你在API文档里找不到你需要的辅助函数,你可能会想自己写新的辅助函数。
这很简单。
一组辅助函数(返回HTML代码的标准PHP函数)被存放在名叫FooBarHelper.php的文件里,FooBar是这这个辅助函数组的名字。
这个文件在app/myapp/lib/help/目录下(或者任意一个lib/目录下的helper/目录),这样做的目的是为了让use_helper('FooBar')辅助函数能自动载入这组辅助函数。
TIP系统允许你覆盖symfony自己的辅助函数。
例如,如果你想重新定义Text辅助函数的所有内容,只要在apps/myapp/lib/helper目录下建立TextHelper.php文件。
当使用use_helpler('Text')的时候symfony会使用你定义的辅助函数而不是系统默认的。
但是请注意:
由于原始文件没有载入,你需要重新定义这组辅助函数里所有的函数,否则某些系统的辅助函数就用不了了。
页面布局
例7-1里的模板不是一个有效的XHTML文档。
它缺少DOCTYPE定义还有与
标签。这是因为它们存放在程序的其他地方,即layout.php这个文件里,它包含页面布局。
这个文件也被称为全局模板,存放所有页面都会使用的HTML代码,这样避免在每个页面里面重复。
模板的内容被包括在布局里,或者说,布局“装饰”模板。
图7-1是这种装饰模式的程序。
TIP想要详细了解装饰模式与其他设计模式,请参考《PatternsofEnterpriseApplicationArchitecture(企业应用架构模式)》这本书,作者是MartinFowler(Addison-Wesley,ISBN:
0-32112-742-0,中文版由机械工业出版社出版书号7-111-14305-1)。
图7-1-用布局装饰模板
例7-5是一个默认的页面布局,在应用程序的templates/目录下。
例7-5-默认布局,myproject/apps/myapp/templates/layout.php
DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http:
//www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
//www.w3.org/1999/xhtml"xml: lang="en"lang="en">
phpechoinclude_http_metas()?
>
phpechoinclude_metas()?
>
phpechoinclude_title()?
>
phpecho$sf_data->getRaw('sf_content')?
>
部分的辅助函数用来取得视图配置文件里面的信息。标签里的内容输出模板的执行结果。这个布局加上例7-1里的模板还有默认的视图配置文件,会得到例7-6的输出。
例7-6-布局,视图配置,还有模板加起来的结果
DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http:
//www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
//www.w3.org/1999/xhtml"xml: lang="en"lang="en">
欢迎
欢迎回来,
phpecho$name?
>!
- 你要做什么?
phpecholink_to('阅读最新的文章','article/read')?
>
phpecholink_to('写一篇新文章','article/write')?
>
每个应用程序的全局模板都可以彻底的修改,添加必要的HTML代码。
布局常常用来放置网站导航,标志等。
你甚至可以有多个布局,不同的动作(action)可以用不同的布局。
不需要担心JavaScript还有样式表的包含问题,在本章的“视图配置”这一节里会介绍如何处理这个问题。
模板快捷变量
在模板里,有一些symfony变量可以直接使用。
通过这些快捷变量可以从symfony的对象里取得一些最常用的模板信息:
∙$sf_context:
完整的环境对象(contextobject)(sfContext类的实例)
∙$sf_request:
请求对象(sfRequest类的实例)
∙$sf_params:
请求的参数
∙$sf_user:
当前的用户session对象(sfUser类的实例)
在上一章里介绍了sfRequest还有sfUser对象的常用方法,这些方法可以在模板里通过$sf_request和$sf_user变量调用。
例如,如果请求里包含total参数,它的值可以在模板里通过下面的方法取得:
//长一点的版本
phpecho$sf_request->getParameter('total');?
>
//短版本
phpecho$sf_params->get('total');?
>
//相当于在动作(action)里面执行下面的代码
echo$this->getRequestParameter('total');
代码片段(CodeFragments)
你可能常常会在好几个页面包含一些HTML或者PHP代码。
为了避免重复,PHP的include()语句大多数时候就足够了。
例如,如果你的程序的很多模板都需要同一段代码,把这断代码存在全局模板目录里(myproject/apps/myapp/templates/)命名为myFragment.php,然后在模板里这样去包含它:
phpinclude(sfConfig:
:
get('sf_app_template_dir').'/myFragment.php')?
>
但是这样封装一段代码并不是一个很好的做法,因为你需要很多变量名来在这段代码与不同的模板之间传递信息。
另外,symfony的缓存系统(将在第12章介绍)不能够检测到这种包含,所以这段代码没法被单独缓存起来。
symfony提供了三种不同的聪明的代码片段来取代include:
∙如果逻辑部分代码量很小,只需要包含一个能访问一些你传递的数据的模板。
这样,你需要用局部模板(partial)。
∙如果逻辑的代码量比较大(例如,你需要访问数据模型,并且根据session修改数据),你可能回想把逻辑与表现分开。
这种情况,你需要用组件(component)。
∙如果这个片段用来替换布局里的特定部分,这个部分有一个默认的内容。
你需要用槽(slot)。
Note还有一种代码片段,组件槽(componentslot),它用于代码片段与环境有关的情况(例如,对一个模块内的不同动作,这段代码需要有所不同)。
组件槽(componentslot)将在稍后介绍。
这些片段由局部模板(Partial)辅助函数组完成。
这些辅助函数不要用声明就可以在symfony模板中使用。
局部模板(Partials)
局部模板是可重用的一段模板。
例如,在一个发布程序里,文章详情页面用来显示文章的代码,也可以用在最佳文章列表和最新文章页面。
这代码就很适合作为局部模板,如图7-2所示。
图7-2-重用局部模板
与模板类似,局部模板也位于templates/目录,也是由HTML代码与嵌入式PHP代码组成。
局部模板文件名以下划线(_)打头,这样可以把它们与同在templates/目录的模板区分开来。
模板中可以包含同一个模块内或者其他模块的局部模板,也可以是在全局的templates/目录中的局部模板。
使用include_partial()辅助函数包含局部模板,参数是模块与局部模板的名字(但是请省略开头的下划线与结尾的.php),如例7-7。
例7-7-在mymodule模块的模板中包含一个局部模板
//包含myapp/modules/mymodule/templates/_mypartial1.php局部模板
//由于模板与这个局部模板在同一个模块里
//可以省略模块名
phpinclude_partial('mypartial1')?
>
//包含myapp/modules/foobar/templates/_mypartial2.php局部模板
//必须些模块名
phpinclude_partial('foobar/mypartial2')?
>
//包含myapp/templates/_mypartial3.php局部模板
//这是'global'模块的局部模板
phpinclude_partial('global/mypartial3')?
>
局部模板中可以使用标准symfony辅助函数和模板快捷变量。
但是由于局部模板可以在任何地方使用,它们不能直接访问使用它们的模板对应的动作定义的变量,除非作为参数传递给它们。
例如,如果你希望局部模板能够访问$total变量,必须由动作(action)先传递给模板,然后模板通过include_partial()辅助函数的第二个参数传递给局部模板,如例7-8,7-9,7-10所示。
例7-8-在动作里定义一个变量mymodule/actions/actions.class.php
classmymoduleActionsextendssfActions
{
publicfunctionexecuteIndex()
{
$this->total=100;
}
}
例7-9-模板把变量传递给局部模板mymodule/templates/indexSuccess.php
Hello,world!
phpinclude_partial('mypartial',
array('mytotal'=>$total)
)?
>
例7-10-局部模板现在可以使用这个变量了mymodule/templates/_mypartial.php
Total:
phpecho$mytotal?
>
TIP到目前为止所有的辅助函数都是通过
phpechofunctionName()?
>这样来调用的。
局部模板辅助函数,直接通过调用就可以了,不需要echo,这有点类似PHP的include()语句。
如果你需要一个能返回局部模板内容而不显示的函数,你可以用get_partial()。
所有本章介绍的include_辅助函数都有一个对应的get_辅助函数,这个get_辅助函数与echo语句配合使用的功能与include_函数相同。
组件(Components)
第2章的第1个例子按照逻辑于表现分成了两部分。
与MVC模式的动作(action)与模板类似,你可能会需要把局部模板分成逻辑部分于表现部分。
遇到这种情况,你需要使用组件。
组件类似于动作(action),不过他要快很多。
组件的逻辑存放在sfComponents类的子类里,位于action/components.class.php里。
它的表现部分存放在局部模板里。
sfComponents类的方法由execute(执行)这个词开头,类似于动作(action),它们传递变量给表现层的方式也与动作(action)一样。
组件的局部模板根据组件的方法命名(去掉execute,前面加下划线)。
表7-1比较了动作与组件的命名方式。
Table7-1-动作与组件命名方式比较
命名方式
动作
shitulingjian
逻辑文件
actions.class.php
components.class.php
继承的类
sfActions
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第07章 深入视图层 07 深入 视图