Helper(帮助类)
Section 1 Helpers
Helper类就是为视图提供了常见且通用的方法,更好更快的格式化或者展现数据。
HTML Helper
介绍
HTML Helper是Cake用来使开发变得迅速且不会乏味的一个好方法。HTML Helper有两个主要的目的:帮助插入那些经常用到的HTML代码,帮助更快更方便的创建一个Form。下面的文章中,我们将介绍绝大多数有用的方法,不过记住 http://api.cakephp.org 永远是最好的参考。
HTML Helper中的许多方法使用了tags.ini.php里面定义的HTML tag定义。Cake的核心配置中包含了这个定义文件,不过如果你希望做些改变,复制一份/cake/config/tags.ini.php,并且放置在 /app/config/ folder 目录下就可以了。HTML Helper会根据这个文件中的定义来为你创建HTML Tag。使用HTML Helper来创建部分视图代码会让工作变得轻松不少(我倒希望尽可能少使用HTML Tag,这种对页面的侵入会导致页面在设计期纯粹成了代码),如果你修改了tag定义文件,这将是一个全局性的改变,请谨慎对待。
另外,如果 AUTO_OUTPUT 被设为true,Helper会自动输出HTML Tag,而不是返回值。这是为了照顾那些不喜欢使用short tag或者大量的echo()调用的开发人员。当然你可以在方法中包含$return参数来强制使用返回值,无论配置文件AUTO_OUTPUT被设置成true或者false。
HTML helper方法也包含了 $htmlAttributes 参数,允许你为tag添加额外的属性。比如如果你希望为你的tag增加class属性,你可以通过 $htmlAttribute 来实现:
array('class'=>'someClass')
插入良好格式的元素
如果你希望使用Cake来插入一些良好格式(通常是大量重复)的HTML元素,HTML Helper在这方面会令你非常满意。Helper中有许多方法可以插入各种媒体资源,帮助创建table,甚至可以帮你通过一个array来创建一个树型列表。
charset
string $charset
boolean $return
生成一个 charset 的META-Tag
css
string $path
string $rel = 'stylesheet'
array $htmlAttributes
boolean $return = false
创建CSS样式文件的链接。$rel参数可以为该tag提供 rel=value,通常为rel='stylesheet'
image
string $path
array $htmlAttributes
boolean $return = false
生成tag,该方法的返回值可以作为参数传入link()方法生成一个图片链接。
link
string $title
string $url
array $htmlAttributes
string $confirmMessage = false
boolean $escapeTitle = true
boolean $return = false
该方法可以在视图中生成一个超链接。$confirmMessage是一个非常有用的参数,很多时候我们需要超链接点击后弹出一个提醒或者是确认信息,以前你需要写一行js,现在只需要定义该参数就ok了。举个例子,通常删除一条记录的 '删除' 链接会弹出一个 “你确认要删除吗?” 的确认框,确认后才触发删除动作。$escapeTitle参数设为true,可以忽略$title属性。
tableHeaders
array $names
array $tr_options
array $th_options
创建指定格式的table表头
tableCells
array $data
array $odd_tr_options
array $even_tr_options
创建指定格式的单元格
guiListTree
array $data
array $htmlAttributes
string $bodyKey = 'body'
string $childrenKey = 'children'
boolean $return = false
创建一个内嵌的
- 列表
表单与校验
通过HTLM helper在视图中快速的创建Form代码真的会让你感觉就像投入代码中的一缕阳光。它会替你生成所有的form tag,出错情况下还会自动帮你回填数据,并显示出错信息。为了让你更好的体会到这种感觉,让我们来看一个例子吧。假定我们现在有了一个Note model,需要创建一个controller,以及建立一个视图来新增和修改Note信息。下面是controller代码:
Edit Action inside of the NotesController
function edit($id)
{
//First, let's check to see if any form data has been
//submitted to the action.
if (!empty($this->data['Note']))
{
//Here's where we try to validate the form data (see Chap. 12)
//and save it
if ($this->Note->save($this->data['Note']))
{
//If we've successfully saved, take the user
//to the appropriate place
$this->flash('Your information has been saved.', '/notes/edit/' . $id);
exit();
}
else
{
//Generate the error messages for the appropriate fields
//this is not really necessary as save already does this, but it is an example
//call $this->Note->validates($this->data['Note']); if you are not doing a save
//then use the method below to populate the tagErrorMsg() helper method
$this->validateErrors($this->Note);
//And render the edit view code
$this->render();
}
}
// If we haven't received any form data, get the note we want to edit, and hand
// its information to the view
$this->set('note', $this->Note->find("id = $id"));
$this->render();
}
controller创建好了,让我们来看一下视图代码(文件在app/views/notes/edit.thtml)。我们的Note model非常的简单,只有Note ID,提交者ID和Note内容3个属性。所以视图页面只需要展示这些数据并供用户来修改。
HTML helper可以在任何一个页面上通过 $html 来调用。
我们只看页面上最核心的那块Form代码:
Edit View code (edit.thtml) sample
<?php echo $html->formTag('/notes/edit/' . $html->tagValue('Note/id')?>
Body: | $html->textarea('Note/body', array('cols'=>'60', 'rows'=>'10')); ?> <?php echo $html->tagErrorMsg('Note/body', 'Please enter in a body for this note.') ?> |
<?php echo $html->hiddenTag('Note/id')?> <?php echo $html->hiddenTag('note/submitter_id', $this->controller->Session->read('User.id'))?> |
<?php echo $html->submit()?>
大部分的form tag生成函数(包括tagErrorMsg)需要你提供 $fieldName。这个参数能够让Cake知道你提交的是什么数据,然后可以对应的去保存和校验数据。$fieldName 参数的格式为 "modelname/fieldname"。如果你要为Note model增加一个title属性,你可以加上下面的代码:
<?php echo $html->input('Note/title') ?>
<?php echo $html->tagErrorMsg('Note/title', 'Please supply a title for this note.')?>
tagErrorMsg()用来输出错误信息,并且会被嵌入
下面是所有HTML helper可以生成的form tag(大部分是一目了然的):
submit
string $buttonCaption
array $htmlAttributes
boolean $return = false
password
string $fieldName
array $htmlAttributes
boolean $return = false
textarea
string $fieldName
array $htmlAttributes
boolean $return = false
checkbox
string $fieldName
array $htmlAttributes
boolean $return = false
file
string $fieldName
array $htmlAttributes
boolean $return = false
hidden
string $fieldName
array $htmlAttributes
boolean $return = false
input
string $fieldName
array $htmlAttributes
boolean $return = false
radio
string $fieldName
array $options
array $inbetween
array $htmlAttributes
boolean $return = false
tagErrorMsg
string $fieldName
string $message
HTML helper中还包含了一组函数来生成日期相关的tag。$tagName参数和$fieldName处理方式类似,提供该日期tag所对应的model属性。当处理数据时,你会发现controller中获得的日期数据被分成了几个部分,你需要做一个连接处理。
Concatenating time data before saving a model (excerpt from NotesController)
function edit($id)
{
//First, let's check to see if any form data has been submitted to the action.
if (!empty($this->data['Note']))
{
//Concatenate time data for storage...
$this->data['Note']['deadline'] =
$this->data['Note']['deadline_year'] . "-" .
$this->data['Note']['deadline_month'] . "-" .
$this->data['Note']['deadline_day'];
//Here's where we try to validate the form data (see Chap. 10) and save it
if ($this->Note->save($this->data['Note']))
{
...
dayOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)
yearOptionTag ($tagName, $value=null, $minYear=null, $maxYear=null, $selected=null, $optionAttr=null)
monthOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)
hourOptionTag ($tagName, $value=null, $format24Hours=false, $selected=null, $optionAttr=null)
minuteOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)
meridianOptionTag ($tagName, $value=null, $selected=null, $optionAttr=null)
dateTimeOptionTag ($tagName, $dateFormat= 'DMY', $timeFormat= '12', $selected=null, $optionAttr=null)
AJAX Helper
Cake Ajax helper使用了最为流行的Prototype和Scriptaculous两个JS库来完成Ajax操作和客户端特效(我相信Prototype改变了很多人对JS的看法,我就是其中一个)。为了使用该Helper,你需要下载最新的Scriptaculous库(http://script.aculo.us),并放置在/app/webroot/js/下面。任何需要使用Ajax helper的页面都能使用该类库。
大部分Ajax helper中的函数都需要一个特别的参数 $options,熟悉Prototype的人应该不会觉得陌生。$options是一个array,可以定义Ajax操作各个选项。下面是选项的简单介绍:
AjaxHelper $options Keys
/* General Options */
$options['url'] //Ajax调用的action的URL。
$options['frequency'] //remoteTimer()或observeField()调用间隔
$options['update'] //根据Ajax调用结果去更新内容的元素DOM ID
$options['with'] //根据指定的ID将元素serialize后随Ajax Form一起提交
$options['type'] //决定调用的方式是异步的还是同步的
/* Callbacks : JS code to be executed at certain
times during the XMLHttpRequest process */
$options['loading'] // 当远程文档被浏览器载入时的回调函数
$options['loaded'] // 当远程文档被浏览器载入完毕后的回调函数
$options['interactive'] // 当用户可以和远程文档交互时的回调函数,忽略是否被载入完毕
$options['complete'] // XMLHttpRequest调用完成时的回调函数
$options['confirm'] // 在发起一个XMLHttpRequest前弹出的确认窗口
$options['condition'] // XMLHttpRequest初始化前的判断条件
$options['before'] // XMLHttpRequest初始化前调用的JS代码
$options['after'] // 在XMLHttpRequest初始化完成但'loading'之前立即被执行的JS代码
下面是一些让你更快更简单使用Ajax的helper函数:
link
string $title
string $href
array $options
boolean $confirm
boolean $escapeTitle
显示一个超链接,$title文本,通过$options['url']获取远程内容并更新$options['update']元素内容,回调函数可以使用。
remoteFunction
array $options
该函数创建远程调用所必需的javascript。主要用来作为linkToRemote的基础函数,并不太由用户直接使用,因为需要你写操作所需的js。
remoteTimer
array $options
以$options['frequency']为频率(单位为秒,默认为10秒),周期性的调用$options['url']定义的远程action。通常用来根据远程调用返回结果来更新一个特定的div(由$options['update']来指定),比如web聊天窗口,NBA文字直播,回调函数可以使用。
form
string $action
string $type
array $options
返回一个form tag来提交到$action,使用XMLHttpRequest在后台提交代替原来页面刷新式的提交方式。form tag中的data和通常的form提交一样(你可以在controller中通过$this->params['form']使用)。提交完成后根据回发的内容来更新$options['update']指定的元素。回调函数可以使用。
observeField
string $field_id
array $options
根据$options['frequency']定义的频率侦测$field_id所指定的元素的内容是否发生变化,如果发生变化调用$options['url']所指定的action。可以根据$options['update']更新指定的元素或者使用$options['with']来提交相应的元素内容。回调函数可以使用。
observeForm
string $form_id
array $options
和observeField()一样的功能,唯一不同的是侦测的是一个form内容的变化。
autoComplete
string $field
string $url
array $options
Scriptaculous中的那个autoComplete恐怕用过的人都会留下极其深刻的印象,而我们所做就是让他变得更好用,虽然他已经非常的好用了。$field指定绑定autoComplete的文本框。$url所指定的action需要返回一个自动完成项的列表:最基本的需要返回一个
function autocomplete ()
{
$this->set('posts',
$this->Post->findAll(
"subject LIKE '{$this->data['Post']['subject']}'")
);
$this->layout = "ajax";
}
(译注:在生产环境下使用自动完成功能,必须使用缓存,否则会带来速度上的瓶颈)
在视图中需要定义个
真正的用户页面上只需要这样定义就能使用该自动完成功能:
<?php echo $ajax->autoComplete('Post/subject', '/posts/autoComplete')?>
<?php echo $html->submit('View Post')?>
autoComplete()函数会根据参数创建一个文本框,并且当你键入内容时会显示一个div包含有自动完成内容供你选择。你可以为该div加上CSS样式,这些style的命名都是Scriptaculous中定义好的,所以你不能随便更改。(译注:有兴趣的话可以看看controls.js,我相信很多情况下默认的功能并不能满足我们的需要)
div.auto_complete {
position :absolute;
width :250px;
background-color :white;
border :1px solid #888;
margin :0px;
padding :0px;
}
li.selected { background-color: #ffb; }
drag
string $id
array $options
使$id指定的元素具有拖曳的能力。你可以通过 $options 来指定一些附加的选项:
// (版本号是scriptaculous的版本号)
$options['handle'] // (v1.0) 可拖曳元素句柄
$options['handle'] // (v1.5) 在1.5中该参数可以为一个CSS class的名称,即可以使用一个字符串。
// 通过该CSS class名称匹配成功的第一个节点作为句柄参数传入,
// 就和1.0版本中的处理是一致了。
$options['revert'] // (v1.0) 当设为true时,拖曳动作停止后会元素自动回到初始的位置。
$options['revert'] // (v1.5) revert参数也可以是一个函数引用,当拖曳动作停止时触发。
$options['constraint'] // 可设置为horizontal(水平)或 vertical(垂直),
// 拖拽动作会限制在水平或者垂直方向上。
drop
string $id
array $options
使$id所指定的元素具备拖放的能力。下面照例是一些设置项:
$options['accept'] // 该参数可以为string或者是JavaScript string数组,包含了CSS class名称。
// 具备拖放能力的元素只接受应用这些CSS class的拖曳元素。
$options['containment'] // 该参数可以为单个元素句柄或者是元素数组,
// 具备拖放能力的元素只接受被包含在这些元素中的拖曳元素。
$options['overlap'] // 该参数可以设为horizontal(水平)或者vertical(垂直),
// 可拖放元素只会在拖曳元素和自己在指定方向上重叠面积超过50%的情况响应该动作。
dropRemote
string $id
array $options
array $ajaxOptions
创建一个拖放元素并为之初始化一个XMLHttpRequest,当一个拖曳元素被拖放至此时,触发一个Ajax动作。$options 参数和drop()一样,$ajaxOptions 参数和link()一样。
sortable
string $id
array $options
sortable函数可以让一个list对象或者是一组floated对象(通过 $id 参数指定DOM ID)可以被排序。$options 数组包含了排序相关的设置:
$options['tag'] // 设定可排序的tag类型(即容器中的子元素)。对于UL和OL来说,
// 子元素类型是LI,对于其他类型的tag则需要你指定子元素类型。默认为li。
$options['only'] // 进一步限定排序子元素,只有应用给定的CSS class的子元素才能被排序。
$options['overlap'] // 可以为vertical(默认) 或者 horizontal。对于floated元素或者是水平列表,
// 请选择 horizontal,而对于垂直列表清选择 vertical。
$options['constraint'] // 限定元素的拖动方向,vertical 或者 horizontal。
$options['containment'] // 允许排序元素间能够拖放。该参数为一个数组,可以是元素句柄,
// 也可以是元素ID,这里说的元素指的都是作为拖放容器的元素。
$options['handle'] // 元素句柄
editor
string $id
string $url
array $options
通过editor函数第一个参数$id所提供的DOM id,为指定的元素创建一个 in-place(现场) Ajax 编辑框。函数执行后,当鼠标悬停该元素时,该元素会高亮显示,当点击时会变为一个单行文本编辑框。editor函数的第二个参数$url,指定了编辑完成后提交的Action。Action会返回更新后的元素内容。更多关于in-place编辑器的选项请参阅Script.aculo.us wiki。
Javascript Helper
Javascript helper旨在帮助开发人员输出良好格式的JS相关tag和数据。
codeBlock
string $string
将 $string 传入的代码包含在 标记内返回。
link
string $url
返回一个 JavaScript标价指向 $url 所指定的脚本引用地址。
linkOut
string $url
和link()函数功能一致,但是假定$url和本应用程序不在同一个域下面。
escapeScript
string $script
去除JavaScript代码中的回车,单引号和双引号。
event
string $object
string $event
string $observer
boolean $useCapture
使用Prototype库中的方法来为元素添加一个事件。(正好还有在写关于Prototype的手册,可以参考以了解更多关于Prototype,自卖一下)。
cacheEvents
缓存由event()创建的JavaScript事件。
writeEvents
输出由cacheEvents()缓存起来的事件代码。
includeScript
string $script
[TODO what's meaning]
Number Helper
Number helper中包含了一些非常出色的函数,可以帮助你格式化数值型数据。
precision
mixed $number
int $precision = 3
指定传入参数 $number 的精度为 $precision,并返回。
toReadableSize
int $sizeInBytes
将传入的 byt e数值转换为具备更高可读性的数值单位。根据传入的数值,函数会返回适合的结果,并选择使用KB, MB, GB 或者 TB等单位。
toPercentage
mixed $number
int $precision = 2
将传入的数值格式化为相应的百分比形式返回。
Text Helper
Text helper提供了一些格式化文本数据的函数。
highlight
string $text
string $highlighter = '\1'
[TODO check the src]
stripLinks
string $text
根据$length参数的长度截取字符串并加上'...',后缀可通过$ending参数来定义。(译注:Prototype1.5新加的方法,默认截取长度为30,刚写完Prototype相关内容。)
从$text文本中截取摘录,摘录$phrase为中心,前后各$radius个字符的文本片段后返回。
Time helper提供了一些函数供程序员输出诸如Unix时间戳格式或者是更加易读的日期字符串。
所有的函数都能够接受合法的PHP日期字符串或者是Unix时间戳格式的参数。
返回完整格式化后的日期字符串,格式为"D, M jS Y, H:i" 或者 'Mon, Jan 1st 2005, 12:00'。
和nice()功能一致,不过对于昨天,今天会返回更加易读的"Today, 12:00" "Yesterday, 12:00"这样的格式。
将日期字符串转换为Unix时间戳格式,即PHP中strtotime()函数的包装函数。
返回一个相对日期或者一个格式化的日期,此日期取决于当前时间和给定时间的差。$datetime的格式应该是strtotime()可解析的,像MySQL的格式。
和timeAgoInWords()非常类似,但是多了输出未来时间戳的能力(例如 "Yesterday, 10:33", "Today, 9:42", 和 "Tomorrow, 4:34")。
如果指定的时间在指定的间隔内,返回true,否则返回false。时间间隔应该以数字的格式指定,单位也是:'6 hours', '2 days'等。
你在编写视图的时候是不是需要一些帮助?如果你发现有一些特别的视图逻辑,而且重复使用,你可以为此创建自己的Helper。
class LinkHelper extends Helper
function makeEdit($title, $url)
// Logic to create specially formatted link goes here...
决定是输出还是返回字符串,选择是基于AUTO_OUTPUT选项的设置(在 /app/config/core.php)和$return参数的值来决定的。你应该使用该函数来返回所有的数据给视图。
让我们使用output()来格式化我们的超链接和URL,并将数据返回给视图。
/app/views/helpers/link.php (logic added)
class LinkHelper extends Helper
function makeEdit($title, $url)
// Use the helper's output function to hand formatted
");}
}
包含其它的Helper
可能你会在你的Helper中用到其它现有的Helper。你可以在$helper array里指定你想使用的外部helper,和你在controller包含其它controller的格式一样。
/app/views/helpers/link.php (using other helpers)
class LinkHelper extends Helper
{
var $helpers = array('Html');
function makeEdit($title, $url)
{
// Use the HTML helper to output
// formatted data:
$link = $this->Html->link($title, $url, array('class' => 'edit'));
return $this->output("
}
}
使用自定义的Helper
当你创建了自己的Helper并将其放置在/app/views/helpers/目录下,你就可以通过在controller中$helpers array变量中包含该Helper来使用它。
class ThingsController
{
var $helpers = array('Html', 'Link');
}
如果你打算再别处使用Html Helper,记住也要包含Html Helper。命名约定和Model一样。
LinkHelper = 类名
link = helpers array中的key
link.php = php文件的名字
捐献您的代码,我们提倡和鼓励您贡献您自定义的帮助类。