视图助手(View Helper)在你的视图脚本中,经常需要执行某些特定的复杂的功能:例如,格式化日期,生成表单对象,或者显示action的链接等等。你可以使用助手类来完成这些工作。
助手就是简单的类。假设你想要一个名为'fooBar'的助手,缺省地,类的前缀是
在视图脚本中,你可以用 基本的助手
以上helper的使用非常简单,下面是个例子。注意你只需要调用即可,它们会根据需要自己加载并实例化。 <?php // 在你的view脚本内部, $this 指向 Zend_View 实例. // // 假设你已经为select对应的变量$countries指定一系列option值, // array('us' => 'United States', 'il' => // 'Israel', 'de' => 'Germany'). ?> <form action="action.php" method="post"> <p><label>Your Email: <?php echo $this->formText('email', 'you@example.com', array('size' => 32)) ?> </label></p> <p><label>Your Country: <?php echo $this->formSelect('country', 'us', null, $this->countries) ?> </label></p> <p><label>Would you like to opt in? <?php echo $this->formCheckbox('opt_in', 'yes', null, array('yes', 'no')) ?> </label></p> </form> 以上视图脚本会输出这样的结果: <form action="action.php" method="post"> <p><label>Your Email: <input type="text" name="email" value="you@example.com" size="32" /> </label></p> <p><label>Your Country: <select name="country"> <option value="us" selected="selected">United States</option> <option value="il">Israel</option> <option value="de">Germany</option> </select> </label></p> <p><label>Would you like to opt in? <input type="hidden" name="opt_in" value="no" /> <input type="checkbox" name="opt_in" value="yes" checked="checked" /> </label></p> </form> 动作视图助手
内部调用
Example #1 动作视图助手的基本用法
例如,假设你有一个 <div id="sidebar right"> <div class="item"> <?= $this->action('list', 'comment', null, array('count' => 10)); ?> </div> </div> 区域助手(Partial Helper)
Example #2 Partials 的基本用法 partials 的基本用法是在它自己的视图范围内解析一个模板的片段。 <?php // partial.phtml ?> <ul> <li>From: <?= $this->escape($this->from) ?></li> <li>Subject: <?= $this->escape($this->subject) ?></li> </ul> 你可以这样从视图脚本里调用它: <?= $this->partial('partial.phtml', array( 'from' => 'Team Framework', 'subject' => 'view partials')); ?> 解析结果如下: <ul> <li>From: Team Framework</li> <li>Subject: view partials</li> </ul>
Example #3 使用 PartialLoop 来解析可迭代的(Iterable)的模型 可能你常常会需要在一个循环里使用 partials 来输出相同的内容片段多次,这时你就可以把大块的重复的内容或复杂的显示逻辑放到一个地方。然而这对性能有影响,因为partial助手需要在每个迭代里调用一次。
让我们看一下下面的 partial 视图脚本: <? // partialLoop.phtml ?> <dt><?= $this->key ?></dt> <dd><?= $this->value ?></dd> 添加下列 "model": <?php $model = array( array('key' => 'Mammal', 'value' => 'Camel'), array('key' => 'Bird', 'value' => 'Penguin'), array('key' => 'Reptile', 'value' => 'Asp'), array('key' => 'Fish', 'value' => 'Flounder'), ); ?>
在视图脚本中,你可以这样调用 <dl> <?= $this->partialLoop('partialLoop.phtml', $model) ?> </dl> <dl></dl> <dt>Mammal</dt> <dd>Camel</dd> <dt>Bird</dt> <dd>Penguin</dd> <dt>Reptile</dt> <dd>Asp</dd> <dt>Fish</dt> <dd>Flounder</dd> </dl> Example #4 在其它模块中解析 Partials
有时候 partial 存在于不同的模块(Module)。如果你知道模块的名称,你可以把它当作第二个参数传递给 例如,如果一个你想用一个在 'list' 模块的 pager partial,就象下面这样来运用: <?= $this->partial('pager.phtml', 'list', $pagerData) ?> 这样,你可以重用原来是特别供给其它模块使用的 partials 。所以,在共享的视图脚本路径里放置可重用的 partials 很可能是个好习惯。 占位符助手(Placeholder Helper)
Example #5 占位符的基本用法
占位符的基本用法是将视图中的数据持久化。每个 <?php $this->placeholder('foo')->set("Some text for later") ?> <?php echo $this->placeholder('foo'); // outputs "Some text for later" ?> Example #6 用占位符来聚合内容 通过占位符来聚合内容有时候很有用。例如视图脚本可拥有一个变量数组来存放数据,而视图脚本可以决定这些数据如何显示出来。
<!-- first view script --> <?php $this->placeholder('foo')->exchangeArray($this->data) ?> <!-- later view script --> <?php $this->placeholder('foo')->setPrefix("<ul>\n <li>") ->setSeparator("</li><li>\n") ->setIndent(4) ->setPostfix("</li></ul>\n"); ?> <?php echo $this->placeholder('foo'); //输出一个带有漂亮缩进的HTML无序列表 ?>
因为 <?php $this->placeholder('foo')->bar = $this->data ?> <?php echo $this->placeholder('foo')->bar ?> <?php $foo = $this->placeholder('foo'); echo $foo['bar']; ?> Example #7 使用占位符(Placeholders)来抓取内容
有时你可能会在视图脚本(最容易的模板)为占位符放些内容,
<!-- Default capture: append --> <?php $this->placeholder('foo')->captureStart(); foreach ($this->data as $datum): ?> <div class="foo"> <h2><?= $datum->title ?></h2> <p><?= $datum->content ?></p> </div> <?php endforeach; ?> <?php $this->placeholder('foo')->captureEnd() ?> <?php echo $this->placeholder('foo') ?> <!-- Capture to key --> <?php $this->placeholder('foo')->captureStart('SET', 'data'); foreach ($this->data as $datum): ?> <div class="foo"> <h2><?= $datum->title ?></h2> <p><?= $datum->content ?></p> </div> <?php endforeach; ?> <?php $this->placeholder('foo')->captureEnd() ?> <?php echo $this->placeholder('foo')->data ?> 具体占位符实现Zend Framework 自带有若干个具体实现的占位符,包括常用的占位符:doctype、page title、以及各种 <head> 元素。对所有情况,不带参数调用占位符将返回元素自己。 每个元素的文档,请查看如下链接: 文档类型助手(Doctype Helper)
有效的HTML和XHTML文档应当包括一个
你也可以指定一个自己定制的带有良好结构的文档类型。
Example #8 Doctype 助手的基本用法 在任何时候都可以指定 doctype。然而,依赖 doctype 输出的助手只在你设置后才认识它,所以最简单的用法是在 bootstrap 脚本中指定: $doctypeHelper = new Zend_View_Helper_Doctype(); $doctypeHelper->doctype('XHTML1_STRICT'); 然后在布局脚本中输出: <?php echo $this->doctype() ?> Example #9 获取 Doctype
如果需要知道文档类型,可以在由调用助手返回的对象中调用 <?php $doctype = $view->doctype()->getDoctype(); ?>
很常见地,你需要知道doctype是否XHTML;那么, <?php if ($view->doctype()->isXhtml()) { // do something differently } ?> HeadLink 助手
HTML的
另外,
Example #10 HeadLink 助手的基本用法
任何时候可以指定 <?php // 在视图脚本中设置链接: $this->headLink()->appendStylesheet('/styles/basic.css') ->headLink(array('rel' => 'favicon', 'href' => '/img/favicon.ico'), 'PREPEND') ->prependStylesheet('/styles/moz.css', 'screen', true); ?> <?php // 解析链接:?> <?= $this->headLink() ?> HeadMeta 助手
HTML
也可以用
Example #11 HeadMeta 助手基本用法 你可以在任何时候指定一个新的meta标签。例如指定客户端缓冲规则或SEO关键字。 例如,如果想指定SEO关键字,要创建带有名为'keywords'和内容(在页面上和关键字有关联的)的meta名称标签: <?php // setting meta keywords $this->headMeta()->appendName('keywords', 'framework php productivity'); ?> 如果想设置一些客户端缓冲规则,最好设置带有想执行的规则的 http-equiv 标签: <?php // 禁止客户端缓存 $this->headMeta()->appendHttpEquiv('expires', 'Wed, 26 Feb 1997 08:21:57 GMT') ->appendHttpEquiv('pragma', 'no-cache') ->appendHttpEquiv('Cache-Control', 'no-cache'); ?> meta标签的另一个流行用法是设置内容类型,字符集和语言: <?php // setting content type and character set $this->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=UTF-8') ->appendHttpEquiv('Content-Language', 'en-US'); ?> 最后一个例子,可以使用"meta refresh" 来让页面转向,一个简单的办法来显示过渡消息: <?php // 设置以下meta可使页面3秒钟后转向一个新的url $this->headMeta()->appendHttpEquiv('Refresh', '3;URL=http://www.some.org/some.html'); ?> 在布局脚本(layout)中放置所有meta标签后,简单地echo助手,把所有内容输出: <?= $this->headMeta() ?> HeadScript 助手
HTML
对于所有
最后,你也可以用
The
Example #12 HeadScript 助手基本用法 在任何时候可以指定一个新的脚本。如上所述,可以链接到外部资源文件或脚本自己。 <?php // adding scripts $this->headScript()->appendFile('/js/prototype.js') ->appendScript($onloadScript); ?> 在客户端脚本编程中,顺序常常很重要,因为依赖的缘故,需要确保按特定的顺序来加载库,使用 append、 prepend 和 offsetSet 指令来帮助完成任务: <?php // 按顺序放置脚本文件 //设置偏移量来确保这个文件最后加载 $this->headScript()->offsetSetScript(100, '/js/myfuncs.js'); //使用scriptaculous效果文件,这时append动作使用索引101,接上行代码的索引 $this->headScript()->appendScript('/js/scriptaculous.js'); //但总是保证prototype文件首先加载 $this->headScript()->prependScript('/js/prototype.js'); ?> 当准备好输出所有脚本到布局脚本,简单地 echo 这个助手: <?= $this->headScript() ?> Example #13 Capturing Scripts Using the HeadScript Helper
有时候,需要“编程式”地生成客户端脚本。你可以使用字符串串联、heredoc或类似的技术(字符串串联即$string1.$string2这种形式,heredoc即使用<<<操作符--Haohappy注),通常通过创建脚本和在PHP标签里做手脚会更容易些。 <?php $this->headScript()->captureStart() ?> var action = '<?= $this->baseUrl ?>'; $('foo_form').action = action; <?php $this->headScript()->captureEnd() ?> 下面是上例中的一些假设:
HeadStyle 助手
在 HTML
对于所有情况,
最后,你也可以用
Example #14 HeadStyle 助手的基本用法 在任何时候都可以指定一个新的样式标签: <?php // adding styles $this->headStyle()->appendStyle($styles); ?> 对 CSS 来说,顺序非常重要,因为层叠的顺序(the order of the cascade),你需要确保样式表中的声明按特定的顺序加载。使用append、 prepend 和 offsetSet 指令可帮助你达到目的: <?php // Putting styles in order // place at a particular offset: $this->headStyle()->offsetSetStyle(100, $customStyles); // place at end: $this->headStyle()->appendStyle($finalStyles); // place at beginning $this->headStyle()->prependStyle($firstStyles); ?> 当准备好在布局脚本里输出所有样式声明,简单地 echo 助手: <?= $this->headStyle() ?> Example #15 用 HeadStyle 助手抓取样式声明
有时候需要用程序生成 CSS 样式声明。当你可以使用字符串串联,heredoc等等, 通常通过创建脚本和在PHP标签里做手脚会更容易些。 <?php $this->headStyle()->captureStart() ?> body { background-color: <?= $this->bgColor ?>; } <?php $this->headStyle()->captureEnd() ?> 下面是一些假设:
HeadTitle 助手
HTML
Example #16 HeadTitle 助手基本用法 你可以在任何时候指定一个标题标签。一般的用法可以让你在应用程序的每一个层次来设置标题段:站点、控制器、动作和潜在的资源。 <?php // setting the controller and action name as title segments: //把控制器和动作的名称设置为标题的一部分 $request = Zend_Controller_Front::getInstance()->getRequest(); $this->headTitle($request->getActionName()) ->headTitle($request->getControllerName()); // setting the site in the title; possibly in the layout script: //添加标题内容,这种写法常用于布局脚本中 $this->headTitle('Zend Framework'); // setting a separator string for segments: //为标题的各部分设置分隔符 $this->headTitle()->setSeparator(' / '); ?> 在布局脚本中准备好标题后,使用echo即可输出: <!-- renders <action> / <controller> / Zend Framework --> <?= $this->headTitle() ?> HTML 对象助手
HTML 有四个初始的对象助手:
所有这些助手使用相似的接口。这样,本文档只包含两个助手的例子。 Example #17 Flash 助手 使用助手嵌入 Flash 到你的页面相当简单。唯一需要的参数是资源 URI。 <?php echo $this->htmlFlash('/path/to/flash.swf'); ?> 它输出下列 HTML: <object data="/path/to/flash.swf" type="application/x-shockwave-flash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"> </object>
另外你可以指定可以和 Example #18 通过传递另外的参数来定制对象
对象助手里的第一个参数总是必需的,它是你想嵌入的资源的 URI。
第二个参数只对 echo $this->htmlObject( '/path/to/file.ext', 'mime/type', array( 'attr1' => 'aval1', 'attr2' => 'aval2' ), array( 'param1' => 'pval1', 'param2' => 'pval2' ), 'some content' ); /* 这将输出: <object data="/path/to/file.ext" type="mime/type" attr1="aval1" attr2="aval2"> <param name="param1" value="pval1" /> <param name="param2" value="pval2" /> some content </object> */ InlineScript 助手
HTML
JSON 助手当创建返回 JSON 的视图,设置适当的响应头也非常重要,JSON 视图助手就是来做这个的。另外,缺省地,它关闭(disable)了布局(如果布局是打开(enable)的),因为布局一般不和 JSON 响应一起使用。 JSON 助手设置下列的头: Content-Type: application/json 当解析响应来决定如何处理内容,大部分 AJAX 库寻找这个头。 JSON 助手的用法相当简单: <?php <?= $this->json($this->data) ?> ?> 翻译助手
通常,网站支持多种语言。使用 Zend 翻译 来翻译网站的内容并且 使用
在下面所有的例子里我们使用简单的数组翻译适配器(Array Translation Adapter)。当然你也可以使用任何
Example #19 已注册的实例
为使用已注册的实例就是创建一个 <?php // 我们的例子适配器 $adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de'); Zend_Registry::set('Zend_Translate', $adapter); // 在视图中 echo $this->translate('simple'); // 返回 'einfach' ?> 如果你熟悉 fluent interface ,那么也可以在视图里创建一个实例然后实例化这个助手。 Example #20 在视图里
为了使用 fluent interface ,创建一个 <?php // 在视图里 $adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de'); $this->translate()->setTranslator($adapter)->translate('simple'); // 返回 'einfach' ?>
如果你使用没有 Example #21 直接用法 <?php // 我们的例子适配器 $adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de'); // 实例化适配器 $translate = new Zend_View_Helper_Translate($adapter); print $translate->translate('simple'); // this returns 'einfach' ?>
如果你不用
就象已经知道, Example #22 单个参数 使用单个参数就把它添加到这个方法。 <?php // 在视图里 $date = "Monday"; $this->translate("Today is %1\$s", $date); // 应当返回 'Heute ist Monday' ?>
Example #23 参数列表 使用参数列表并添加给方法。 <?php // 在视图里 $date = "Monday"; $month = "April"; $time = "11:20:55"; $this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date, $month, $time); // 应当返回 'Heute ist Monday in April. Aktuelle Zeit: 11:20:55' ?> Example #24 参数数组 使用参数数组并添加到方法。 <?php // 在视图里 $date = array("Monday", "April", "11:20:55"); $this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date); // 应当返回 'Heute ist Monday in April. Aktuelle Zeit: 11:20:55' ?> 有时候必需要修改翻译的地点。可以通过动态翻译或者把所有的静态翻译来完成。并且你可以使用参数类表和参数数组。在这两种情况下,地点被当作最后一个单个参数给出。 Example #25 动态修改地点 (locale) <?php // 在视图里 $date = array("Monday", "April", "11:20:55"); $this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date, 'it'); ?> 这个例子为 messageid 返回意大利语的翻译。但它将只能用一次。下个翻译将从适配器里设置地点。通常地在添加它到注册表之前你将在翻译适配器里设置期望的地点。但你也可以从助手里设置地点: Example #26 静态修改地点 (locale) <?php // 在视图里 $date = array("Monday", "April", "11:20:55"); $this->translate()->setLocale('it'); $this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date); ?>
在上面的例子里设置
当然,还有 Example #27 获得当前设置的地点 <?php // 在视图里 $date = array("Monday", "April", "11:20:55"); // 从上面的例子里返回 'de' 作为缺省地点 $this->translate()->getLocale(); $this->translate()->setLocale('it'); $this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date); // 返回 'it' 为新的缺省地点 $this->translate()->getLocale(); ?> 助手的路径
就像可以指定视图脚本的路径,控制器也可以为 <?php $view = new Zend_View(); // 设置路径为:/path/to/more/helpers, 通过使用前缀 'My_View_Helper' $view->setHelperPath('/path/to/more/helpers', 'My_View_Helper');
你可以用 <?php $view = new Zend_View(); // Add /path/to/some/helpers with class prefix 'My_View_Helper' $view->addHelperPath('/path/to/some/helpers', 'My_View_Helper'); // Add /other/path/to/helpers with class prefix 'Your_View_Helper' $view->addHelperPath('/other/path/to/helpers', 'Your_View_Helper'); // now when you call $this->helperName(), Zend_View will look first for // "/path/to/some/helpers/HelperName" using class name "Your_View_Helper_HelperName", // then for "/other/path/to/helpers/HelperName.php" using class name "My_View_Helper_HelperName", // and finally for "Zend/View/Helper/HelperName.php" using class name "Zend_View_Helper_HelperName". 编写自定义的助手类编写自定义的助手类很容易,只要遵循以下几个原则即可:
把助手类的文件放在你的助手路径下,
下面是一个 <?php class My_View_Helper_SpecialPurpose { protected $_count = 0; public function specialPurpose() { $this->_count++; $output = "I have seen 'The Jerk' {$this->_count} time(s)."; return htmlspecialchars($output); } }
在视图代码中,可以调用 <?php // remember, in a view script, $this refers to the Zend_View instance. echo $this->specialPurpose(); echo $this->specialPurpose(); echo $this->specialPurpose(); 输出结果如下所示: I have seen 'The Jerk' 1 time(s). I have seen 'The Jerk' 2 time(s). I have seen 'The Jerk' 3 time(s).
有时候需要访问调用 <?php class My_View_Helper_ScriptPath { public $view; public function setView(Zend_View_Interface $view) { $this->view = $view; } public function scriptPath($script) { return $this->view->getScriptPath($script); } }
如果助手类有一个
|