5.9 共通功能——由PEAR::HTML_Menu&Zend_Cache实现的动态清晰的网站导航菜单
拥有一个清晰的导航菜单是成功网站的重要因素。让用户在浏览网站时,能够自由地链接向他想浏览的网页,同时应该通过菜单让用户随时了解他处于在网站的什么位置。通常会采用一种称为面包屑导航(breadcrumbs list)菜单的方式,让用户随时了解他现在所处的位置。
本系统中除了采用了面包屑导航菜单外,还有在网页右上角的,随着用户的登录状态与模块改变的导航菜单,以及网页上部固定的内容分类菜单,如图所示。
导航菜单
要点
面包屑导航菜单
面包屑导航(breadcrumbs list)菜单就是以“>>”样的字符分开的链接系列(按照“上上级网页>>上级>>本网页”的顺序),用户可以通过这个导航菜单知道现在所处的位置,并且可以直接通过面包屑导航菜单跳转到上级页面。
本节利用PEAR::HTML_Menu程序库来生成面包屑导航菜单,PEAR::HTML_Menu程序库可以生成各种各样的菜单(导航链接),通过改变参数就可以简单地改变菜单的形式。PEAR::HTML_Menu程序库可以生成的菜单形式如表5-12所示。
表5-12 PEAR::HTML_Menu程序库可以生成的菜单形式
使用PEAR::HTML_Menu时,为生成阶层状结构的菜单,必须要准备下述结构的数组。
例如,以本系统为例,将生成下面的数组。
当然从可维护性的角度考虑,如果是以固定的形式定义这个数组,是很不合适的。这里利用数据库中保存的信息来动态地生成这个数组。初看起来代码可能显得比较复杂,可以尝试从上述的结果数组来反向理解这段代码。
顶部导航菜单
顶部导航菜单的导航菜单是随着用户的登录状态,以及模块(module)或子系统的不同而呈现不同的样子。
本系统包括默认模块(default)在内,还有书签(bookmark)以及站内留言(message)三个模块。默认模块与站内留言模块采用相同的顶部导航菜单,这样就有默认模块与书签模块两种类型的模块。对于默认模块来讲有用户登录与未登录两种状态。而书签模块来说,有登录与未登录,以及访问自己的书签以及别人书签的四种情况。所有可能的顶部菜单见表5-13。
表5-13 顶部菜单一览
本系统将所有的可能菜单保存在表sitemenu中,并将上述顶部菜单一览保存在表topmenu中,通过程序来实现动态的顶部菜单。当想维护顶部菜单时,只用修改上述两个表的内容即可。
目录结构
数据库的表结构
URI与网页信息对照表(metadata)参照5.8节。其他两个表分别如表5-14和表5-15所示。
表5-14 菜单管理表(sitemenu)
表5-15 顶部菜单管理(topmenu)
代码
一般情况下,菜单并不是频繁更新的东西,这样的信息每次从数据库中取出,再格式化,显然没有效率。因此,这里采取将生成的数组保存在缓冲(Cache)中。
使用Zend_Cache组件实现缓冲的功能。首先使用factory方法生成进行缓冲的Zend_Cache_Frontend对象。在factory方法中依次指定使用的前台终端(缓冲方法)的种类,使用的后台终端(缓冲的保存目录),前台终端的选项,后台终端的选项(关于这些选项请参照节后的补充资料)。这里指定的Core前台终端是提供最基本的缓冲功能的前台终端,File后台终端显示是以文件的形式保存缓冲的。
load方法将指定关键字的从缓冲取出来(指定关键字的缓冲不存在时,返回FALSE)。
这里,当load方法返回FALSE时,13行到16行取得菜单信息,并生成新的缓冲(load方法取得的缓冲值的情况下,直接将其设置到变量$menu中)。
setNode方法取得菜单信息(下面有详细介绍)。这里以setNode方法生成的数组为基础生成HTML_Menu对象。HTML_Menu是PEAR::HTML_Menu程序库的中心类,完成从菜单信息的解析到导航链接的生成的工作。
这里将HTML_Menu对象以menu的名字保存在缓冲中,使用Zend_Cache::save方法进行保存工作。
PEAR::HTML_Menu程序库是以当前的URL作为主键生成导航链接的(例如面包屑菜单的情况下,是生成以当前页为起点,到首页为止的路径。在前后链接的情况下,生成以当前页为基础点,到其前后页的链接)。
这样,在PEAR::HTML_Menu中生成菜单时,首先要设定正确的当前页的URL。PEAR::HTML_Menu中能默认设置当前页的基础名(文件名),这里这个信息没有用,因此,必须使用forceCurrentUrl方法强制将现在的请求URL设置到PEAR::HTML_Menu中。
由于本系统采用了别名URL这个(5.11节有详细介绍)特殊的隐藏URL的方式,需要将URL转换为“/用户ID/别名”的形式(事先在数据库中存储的是“/myfrontuserid/别名”)。当然并不是所有URL都要进行转换,使用checkAlias进行判别,关于checkAlias方法同样在5.11节中有详细的介绍。
使用HTML_Menu_DirectRenderer对象实际输出由HTML_Menu对象管理的菜单信息。PEAR::HTML_Menu程序库提供了各种各样的Renderer(输出引擎),在大多数情况下,使用HTML_Menu_DirectRenderer是没有问题的。Renderer提供了设定输出形式的各种方法(见补充资料)。这里使用最基本的setMenuTemplate方法进行菜单整个外框的设定。HTML_Menu_DirectRenderer方法默认设定菜单的外框,看起来效果并不好,这里不输出外框了。
使用HTML_Menu::render方法进行菜单实际输出形式的格式化。render方法的参数依次为使用的Renderer,输出的菜单种类。能够指定的菜单种类请参照要点,这里设为urhere(面包屑导航菜单)。
Renderer的输出结果,使用toHtml方法以HTML形式输出。此处将生成的HTML字符串直接设定到注册表(registory)中,关于registory的说明请参见补充资料。
定义生成菜单信息的setNode方法。setNode方法有三个参数,依次为数据库连接对象、父菜单ID、基础URL。
上面的第14行调用setNode方法时,将第二个参数设为0,首先将根(即首页)菜单取出,然后依次取得其子菜单,直至最底部的子菜单为止。
以参数$parent为条件,从metadata表中取得菜单信息。36行到40行中,将取得的菜单信息按顺序追加到$result数组中(url值按照“基础URL/别名”的形式,进行格式化)。
取得当前菜单的子菜单,并追加到sub键中。
本方法的关键就是这种递归调用,一直追溯到最底层的子菜单。
最后返回生成的数组。
调用getMenuInfo方法生成default模块的顶部菜单。
调用getCategorys方法生成网站主菜单(分类)。
取得登录用户的ID,当用户没有登录时,设为“客人”。
定义生成网站主菜单的方法getCategorys。
从kbn_master表中取得所有信息的分类。
合成分类信息一览页面的URL。
定义default模块的顶部导航菜单,本方法带一个参数,为基础URL。
当登录ID为空,即没有登录时,将标示设为0(默认值为1,即用户已经登录时)。下面会以此为条件取得顶部菜单的内容。
以default模块(main),标示变量flg为条件从表topmenu中搜索菜单信息。
组合菜单的URL。
定义bm模块的顶部导航菜单,本方法带两个参数,依次为基础URL、用户ID(实为书签所有者的用户ID)。
登录用户与所有者用户都为空时,将标示设为2(为调试用,实际运行时不会出现,因此要点中也没有列出来);
登录用户为空,所有者用户非空时,也就是访问其他人的书签(表中的第五种情况)的情况下,将flg设为4。
登录用户非空,所有者为空,将flg设为1(实际访问书签时,书签一定是有所有者的,所以此项实际应用时不会出现);
所有者不等于登录用户时,即表中的第四项。
所有者与登录者一致时,即表中的第三种情况,设为1。
以bm模块,标示变量flg为条件从表topmenu中搜索菜单信息。
调用getMenuInfo方法生成bm模块的顶部菜单。
调用Index.class.php中的getCategorys生成本系统的主页面。
补充
PEAR::HTML_Menu的renderer类
PEAR::HTML_Menu提供几个为了输出菜单用的renderer类(输出引擎),可根据用途自由选择使用。一般情况下,直接生成HTML的HTML_Menu_DirectRenderer类被经常使用。
HTML_Menu_DirectRenderer类中公开了如表5-16所示的方法。根据菜单的输出类型(template模板)适当地采用。setEntryTemplate方法中可使用的模板类型如表5-17所示。
表5-16 HTML_Menu_DirectRenderer类中主要的方法
表5-17 setEntryTemplate方法中可使用的模板类型
Zend_Cache组件中使用可能的参数
在Zend_Cache组件中,通过切换前台与后台来实现各种各样的缓存处理。例如,除了有将缓存对象限制在特定的页面范围,还可以限制在特定的文件,函数/类的处理结果中;缓存的数据除了可以保存在文件中外,还可以保存在数据库或专用服务器上。
本节中,利用了这个当中最基本的Core前台+File前台的组合。表5-18总结了这个组合中可以使用的主要参数。另外,Core前台是所有前台的核心,这里介绍的选项是其他前台中也使用的。File后台中使用可能的主要参数如表5-19所示。
表5-18 Core前台中使用可能的主要参数
表5-19 File后台中使用可能的主要参数
Zend_Registry组件
全局变量在脚本内部部分都能被访问,非常方便。有被过度经常使用的危险,从有名称冲突危险的角度上说,原则上说,要将全局变量的使用限制在最小范围。
这里出现了全局变量的代替手段——Zend_Registry组件。Zend_Registry是管理注册表变量,这个在应用程序任何地方都能访问的变量的组件。使用Zend_Registry后,定义这种全局变量而不占用全局的名称空间。在Zend Framework中如果想利用全局变量时,强烈推荐使用Zend_Registry。
Zend_Registry中值的取得,设置使用get/set方法。
本节将格式化完成的面包屑导航菜单注册到注册表中,在master页中再取出了。
共有条评论 网友评论