|
 
|
[组件][原创]Zend_View_Helper的使用
本帖最后由 七月十五 于 2009-5-16 15:11 编辑
Zend_View_Helper 是一个很不错的东西,
它可以让你将视图中一些零散的代码模块化,优点是:易于使用、便于维护
好像 有一个教程介绍过这个东西 ;看下面之前,可以先看看这个http://www.phpeye.com/article/view/id/47。
Ps: 10.12 修改menu实例。menu数据保存在menu.xml内。
1、一个最简单的例子
一般情况下,在<head></head>中我们要载入一堆css文件或者js文件
<link rel='stylesheet' type='text/css' media='screen' href='/auction/public/styles/cssform.css' />
<link rel='stylesheet' type='text/css' media='screen' href='/auction/public/styles/admin/basic.css' />
<link rel='stylesheet' type='text/css' media='screen' href='/auction/public/styles/admin/table.css' />
<link rel='stylesheet' type='text/css' media='screen' href='/auction/public/styles/admin/topbar.css' />
<link rel='stylesheet' type='text/css' media='screen' href='/auction/public/styles/admin/leftcolumn.css' />
<link rel='stylesheet' type='text/css' media='screen' href='/auction/public/styles/admin/rightcolumn.css' />
<link rel='stylesheet' type='text/css' media='screen' href='/auction/public/styles/admin/middle.css' />
<link rel='stylesheet' type='text/css' media='screen' href='/auction/public/styles/admin/footer.css' />
<script language='javascript' src='/auction/public/scripts/jquery-1.2.1.pack.js'></script>
<script language='javascript' src='/auction/public/scripts/loading.js'></script>
<script language='javascript' src='/auction/public/scripts/jquery/jquery.ajax.js'></script>
在上面的例子里,我载入7个css(当然因为分成不同文件,每个css的确不大),有控制form 也有控制table 当然更多是layout的控制。
载入3个js文件。包括jquery基本文件以及基本的loading.js(控制动态载入css和js的文件)和一个ajax扩展
这样的代码 问题是肯定没有的;但是有一天,我们要修改其中一点怎么办?比如,我们的href目录不在/auction/public/下,而全部转移到/xxx/xxx/下。我们必须找到这个html文件,一条条修改。我举的例子很简单,的确一条条修改起来也不是很麻烦;但是实际上,zf给我们提供一个很好玩的方法。
以上的代码可以这么写:
首先在一个controller文件内定义要载入的文件(因为这是一个基本载入,一般情况下会在init()初始化定义)
<?php
$this->view->loadCssArray =array('cssform','admin/basic','admin/table','admin/topbar','admin/leftcolumn','admin/rightcolumn','admin/middle','admin/footer');
$this->view->loadJsArray = array('jquery-1.2.1.pack','loading','jquery/jquery.ajax');
$this->view->basePublicUrl = '/xx/xx';
?>
然后在header.phtml文件内
//header.phtml文件内
<?php
echo $this->loadCss($this->loadCssArray,$this->basePublicUrl);
echo $this->loadJs($this->loadJsArray,$this->basePublicUrl);
?>
如果做debug测试,发现$this 其实就是系统里的Zend_View实例。那么loadCss loadJs这个方法怎么来的呢?
其实添加方法,不是使用继承Zend_View,而是使用Zend_View_Helper
//LoadCss.php 文件
class Zend_View_Helper_LoadCss {
public function loadCss($_loadCssArray,$baseUrl,$type = ''){
$html = '';
if(empty($type)){
$type = 'screen';
}
foreach ($_loadCssArray as $_cssFile){
$str ="<link rel='stylesheet' type='text/css' media='".$type."' href='".$baseUrl.".$_cssFile.".css' />";
$html.= $str;
}
return $html;
}
}
//LoadJs.php 文件
class Zend_View_Helper_LoadJs {
public function loadJs($_loadJsArray,$baseUrl){
$html = '';
foreach ($_loadJsArray as $_jsFile){
$str ="<script language='javascript' src='".$baseUrl.".$_jsFile.".js'></script>";
$html.= $str;
}
return $html;
}
}
这两个文件,放的位置,是要看你的Zend_View基本路径的设定的;一般情况下,view文件下下存在三个文件夹,scripts就是我们一般的视图文件目录,而helper文件夹就是存放这些视图帮手的地方。
这样,如果要修改载入那些文件,就只需要修改controller.php内的设定即可。
以上只是一个简单的例子。因此也许有人觉得直接写在header.phtml内更直观,更简单。也许是的;但是对于更复杂的html结构,有时候这种模块化,还是很有效的。
2、一个Menu的例子
我再举一个menu菜单的例子。这个例子的实例可以参考 http://160.26.139.83/admin 用户名:yyy 密码:yyy
一个简单的菜单,一般情况有一个总标题,然后下面几个子菜单。
因为项目都是ajax实现,这个菜单要自动生成ajax连接,并且保证在ajax之前,必要的js文件和css文件载入成功。(动态载入js必须在页面也就是ajax提交前,文件载入成功,否则js不生效)
先介绍Controller下的Action
[php]
//10.15 修改该函数;菜单数据保存在 menu.xml内
public function menuAction(){
$type = 'admin';
$xmlfile = CONFIG_DIR.DIRECTORY_SEPARATOR.'menu.xml';
//这是一个读取xml文件类;如果cache已经保存该文件,从cache内读取
$xmlObject = Htmlhelper_Xml::getLangXml('menu',$xmlfile);
//实例为 管理界面的菜单,所以取管理端菜单数据
$_menuArray = $xmlObject->$type->toArray();
//获得菜单的css class设置数据
$_classArray = $xmlObject->class->toArray();
//获得菜单的ajax设定的基本数据
$_ajaxArray = $xmlObject->ajax->toArray();
$_ajaxArray['baseurl'] = $this->_baseUrl;
$this->view->menuArray = $_menuArray;
$this->view->classArray = $_classArray;
$this->view->ajaxArray = $_ajaxArray;
$this->render();
}
[/php]
menu.xml 我就贴一部分。
<?xml version="1.0" encoding="utf8"?>
<configdata>
//定义管理端菜单内容
<admin>
//标题为 usermenu -〉这个数值将会根据当前语言设定进行转化,比如中文的情况,显示‘用户操作’
<usermenu>
//usermenu下面的菜单
<userlist>
<href>#</href>
<onclick>admin/user/index/ajaxid/mainbody/orderby/orders</onclick>
</userlist>
</usermenu>
<ordermenu>
<orderregister>
<href>#</href>
<onclick>admin/order/register/ajaxid/mainbody</onclick>
//这个连接之前要载入的css和js文件
<css>jquery/jquery.calendar</css>
<js>jquery/jquery.calendar.pack</js>
</orderregister>
</ordermenu>
</admin>
//用户端菜单示例
<user>
<usermenu>
<useredit>
<href>#</href>
<onclick>user/edit/ajaxid/mainbody</onclick>
</useredit>
</usermenu>
</user>
//这个部分是菜单的css class设定
<class>
<title>titlebar</title>
<title_style>MARGIN-TOP: 0px</title_style>
<ul>ddmarkermenu</ul>
<li></li>
</class>
//ajax设定
<ajax>
<id>mainbody</id>
<function>ajaxRequest</function>
</ajax>
</configdata>
然后是Zend_View_Helper_Menu;有了这个类,我们将在视图文件内直接使用$this->menu($array)即可生成菜单。
Ps: 10.15 该类进行修改,将原来代码分解。
[php]
class Zend_View_Helper_Menu {
/**
* 通过数组产生菜单
* @param array $_basicLangMenuArray 语言包数据 比如将'usermenu' 显示为 '用户操作'
* @param array $_menuArray 菜单数据
* @param array $_classArray css数据
* @param array $_ajaxArray ajax数据
* @throws Exception
* @return string
*/
public function menu($_basicLangMenuArray,$_menuArray,$_classArray,$_ajaxArray){
$_titleClass = isset($_classArray['title'])?$_classArray['title']:'titlebar';
$_titleStyle = isset($_classArray['title_style'])?$_classArray['title_style']:'MARGIN-TOP: 0px';
$_ulClass = isset($_classArray['ul'])?$_classArray['ul']:'ddmarkermenu';
$_liClass = isset($_classArray['li'])?$_classArray['li']:'';
$html ='';
if(!isset($_ajaxArray['id'])){
$_ajaxArray['id'] = 'mainbody';
}
if(!isset($_ajaxArray['function'])){
$_ajaxArray['function'] = 'ajaxRequest';
}
//产生标题前的img html代码
$_menuImg = $this->getMenuImg($_ajaxArray);
foreach ($_menuArray as $_menuName=>$_menuValue){
//产生标题部分的代码,其中一个参数就前面产生的标题图标$_menuImg
$html .= $this->getMenuTitle($_basicLangMenuArray,$_menuName,$_menuImg,$_titleClass,$_titleStyle);
if(empty($_menuValue)){
continue;
}
$liHtml ='';
//生成 <ul>之后的<li>部分的html代码
if(is_string($_menuValue)){
$liHtml .= $this->getMenuLiString($_basicLangMenuArray,$_menuValue,$_liClass);
}elseif(is_array($_menuValue)){
$liHtml .= $this->getMenuLiArray($_basicLangMenuArray,$_menuValue,$_liClass,$_ajaxArray);
}
//将刚才生成 的<li>全部放进<ul>内
$html .= $this->getMenuUi($liHtml,$_ulClass);
}
return $html;
}
}
[/php]
有了这个View_helper类,视图文件就变得很简单了。看看只有一行代码(js的不算)
<?php echo $this->menu($this->basicLangXml->menu->toArray(),$this->menuArray,$this->classArray,$this->ajaxArray);?>
<script type="text/javascript">
$(document).ready(function() {
$('#leftcolumn').myInitMenu();
});
</script>
注意,这里没有生成任何javascript的东西。而是将$_menuList数据都以属性的方式存在html内
<div class="titlebar" style="margin-top: 0px;" index="usermenu"><img border="0" src="/auction/public/images/arrow/down_sort_arrow.png"/>用户操作</div>
<ul class="ddmarkermenu" style="display: none;"> <li class="
"><a alt="userlist" ajaxid="mainbody" ajaxurl="admin/user/index/ajaxid/mainbody/orderby/orders" ajax="1" href="#">用户列表</a></li>
<li class="
"><a alt="userregister" ajaxid="mainbody" ajaxurl="admin/user/register/ajaxid/mainbody" ajax="1" href="#">用户注册</a></li>
<br/>
</ul>
如果你使用firebug查看html代码,发现这里没有一句javascript;这个连接的onclick方法,还有标题点击颜色变化等,都是在 $('#leftcolumn').myInitMenu(); 中定义的。
这是一个基本原则,html和js要尽量分开。
而myInitMenu()方法,是本人的一个jquery的简单插件。
[php]
//jquery.mymenu.js
(function($) {
$.fn.myInitMenu = function(options) {
return this.each(function() {
options = $.extend({
default_menu: 'usermenu',
default_ul: 'userlist',
div: $(this).attr('id'),
title: ".titlebar",
link: "ul li a",
link_ajaxAttr: "ajax",
color: "#99CC33",
down_img:_baseUrl+'/public/images/arrow/down_sort_arrow.png',
right_img:_baseUrl+'/public/images/arrow/right_sort_arrow.png',
img: _baseUrl+'/public/images/dynamicdrive/topgradient.jpg'
}, options || {});
$(this).find(options.title+"[@index!='"+options.default_menu+"']").next().hide().end().find("img").attr('src',options.down_img);
$(this).find(options.title+"[@index='"+options.default_menu+"']").css('background','url('+options.img+') repeat-x center center').find("img").attr('src',options.right_img);
$(this).find(options.link+"[@alt='"+options.default_ul+"']").css('color','red').css('background-color',options.color);
//titlebar操作
$(this).find(options.title).click(function(){
$('#'+options.div+' '+options.title).css('background','').next().hide().end().find("img").attr('src',options.down_img);
$(this).css('background','url('+options.img+') repeat-x center center').find("img").attr('src',options.right_img).end().next().slideToggle();
});
//如果不存在ajaxid 产生普通link;否则产生 ajax link
$(this).find(options.link).click(function(){
$('#'+options.div+' '+options.link).removeAttr('style');
$(this).css('color','red').css('background-color',options.color).find("img[@alt='"+$(this).attr('alt')+"']").show();
ajax = $(this).attr(options.link_ajaxAttr);
if(ajax == '1'){
$(this).ajaxMyMenuLink();
return false;
}
});
});
};
$.fn.ajaxMyMenuLink = function(options) {
return this.each(function() {
options = $.extend({
cssAttr: 'cssfile',
jsAttr: 'jsfile',
ajaxAttr: 'ajaxid',
ajaxUrl: 'ajaxurl',
cssLoad: 'cssmenu',
jsLoad : 'jsmenu'
}, options || {});
_cssfile = $(this).attr(options.cssAttr);
_jsfile = $(this).attr(options.jsAttr);
if(_cssfile == '' || typeof _cssfile != 'string'){
_loadcss = 1;
}else{
_loadcss = loadCss(_cssfile,options.cssLoad);
}
if(_jsfile == '' || typeof _jsfile != 'string'){
_loadjs = 1;
}else{
_loadjs = loadJs(_jsfile,options.jsLoad);
}
if(_loadjs == 1 && _loadcss == 1){
ajaxRequest($(this).attr(options.ajaxAttr),$(this).attr(options.ajaxUrl),'','GET');
}
});
}
})(jQuery);
[/php]
熟悉jquery的朋友,应该看起来没什么大问题。
基本上菜单完成了。
比如菜单再添加一项或者改变标题的css类,就在menu.xml去添加,代码部分甚至都可以不管了。
而如果要修改连接的细节,点击之后颜色的改变等,去修改jquery.mymenu.js 就可以了。
而且最重要的是,有了Zend_View_Helper_Menu和jquery.mymenu.js模块化之后 ,可以随地随时生成menu。
比如http://160.26.139.83/admin里你看到的是管理者菜单;http://160.26.139.83定义的就是普通用户的菜单。
到此,再重提上面说的Zend_View_Helper的好处:
1、易于使用
写好的类,随时可以使用;相反死的html代码,只能从一个文件copy到另外一个文件
2、便于维护
做好参数,很多值就只是参数传递的问题了。比如http://160.26.139.83/admin 中的菜单,很多js是动态载入的;尤其是Study Example的部分,可能一个子菜单就需要N多js支持。这些定义、修改,让我在30K的html页面里找出来,真的很麻烦。(http://160.26.139.83/admin 的菜单部分,如果真是原始的html实现,代码量肯定超过30K)
3、养眼,看起来更面向对象。
赫赫,这个不是理由;但是在视图里看到<?php echo $this->menu($this->menuArray,.....);?> ,肯定比看到一堆html舒服的多。
4、 结合jquery,是我的建议。
最近使用jquery,很爽。几乎完全实现js和html的分离;重要的是利用jquery做到这种分离很简单。结合jquery和Zend_View_Helper 可以大大减少zend_view的代码量,而且模块化,可重用。
在http://160.26.139.83/admin 里Study Example里有很多jquery的实例,也是我学习过程的一些测试。
Ps:
http://160.26.139.83/admin 的一些说明
1、请不要在系统设定里,随意修改(不过,我现在也只开放了语言和log等级两项修改);修改成英文或者日语测试完,最好马上恢复到中文。
2、语言包设定里的内容最好不要修改。这里是所有视图显示的东西。
3、用户列表里的test用户,最好不要修改密码或者禁用。很多人在用户端,要用这个id登录的。
[ 本帖最后由 qqinxl 于 2007-10-12 13:59 编辑 ] |
|