因此CMSPAD 1.1的最后一个特性就是支持URL路由(或URL Rewrite?),以下称URLR。那么,CMSPAD是如何支持URLR的呢?下面我们来分析一下URL路径的一些特性。
一个URL由协议、主机、端口、访问路径组成,前三者忽略,说说访问路径吧,它是一个由“/”分隔的一个字符串,用来定位文件位置。正常的一个网站的URL模式为:
http://www.yourcompany.com/index.php
其中“/index.php”就是其访问路径(或叫URI?不知道,自己查查吧)。而好多网站为了隐藏整站程序的实现技术,一般都隐藏了文件后缀,例如:
http://www.yourcompany.com/hello/world/2007/12/20
通过某些URLR技术来进行路径重写到指定脚本文件中。Servlet路径模式匹配和RoR都是这样干的。
因此,如何使用CMSPAD把路径给优化成很不错的感觉呢?其实很简单。
1. 建立一个Dispatcher文件,是PHP的。
dispatch(isset($_SERVER['PATH_INFO'])?$_SERVER['PATH_INFO']:''); //使用PATH_INFO作为参数进行URLR转换。 ?>当然,如果你不想使用PATH_INFO作为路径转换,可以使用其他的数据,例如GET参数。将文件保存在网站目录下,例如 /index.php。
2. 增加 .htaccess 文件:就是写Apache的URL Rewrite规则,这里就不提了。
3. 新建一个Portlet,如果不知道什么叫Portlet,那就看看偶本博客中以前的文章。
class DefaultPortal extends Portlet{ public function pageDefaultPortal($params){ return 'This is home page: '.$params[0]; } public function pageHelloWorld($params){ return 'This is hello world page: '.print_r($params); } }看到了没有,所有的URLR方法都是以“page”开头的,并且有个类型为单项数组的参数($params),并返回输出的内容,将代码保存到Portlet主目录下的DefaultPortal.php文件中。
4. 本节就三个字:搞定鸟。
在测试之前,大家需要了解一下CMSPAD URLR的一些路径处理规则:
1. default: 默认的路径处理方法,格式为 /[PortletName]/[PageName]/[Param1[/Param2[...]]]
2. statics: 伪静态页的路径处理方法,格式为:/[PortletName]/[PageName]/[Param1[,Param2[...]]].html
在这里如果没有PageName,那么CMSPAD将自动匹配到与PortletName同名的方法,例如使用默认模式的路径 /SimplePortlet/100/200/300 将被转换为 /SimplePortlet/SimplePortlet/100/200/300。
如果连PortletName也没有,没事儿,CMSPAD可以通过配置信息变量 $_CONFIG['DISPATCH']['PORTAL'] 来作为默认的Portlet使用;如果连 $_CONFIG['DISPATCH']['PORTAL'] 变量都没有定义,也没事儿,系统会自动使用 DefaultPortal 作为Portlet名字来使用;如果连 DefaultPortal 也没定义,那没办法了,系统会返回404错误。
下面就开始测试了:
把Apache服务器打开,假设以上程序在web根目录下,在浏览器中敲入下列地址 http://localhost/index.php/DefaultPortal/100000,你将会看到以下内容:
This is home page: 100000,而敲入 http://localhost/index.php/DefaultPortal/helloWorld/100/200,则会看到:
This is hello world page: Array([0] => 100, [1] => 200)
而如果使用statics模式,则路径分别为:http://localhost/index.php/DefaultPortal/100000.html 和 http://localhost/index.php/DefaultPortal/helloWorld/100,200.html
这就有个问题了,如果可以任意转换URLR处理器,那么在模板中使用路径时怎么样动态转换路径呢?答案当然是有的啦,哈哈
在模板中,使用hyperlink函数即可实现,例如:
这样,当在后台转换URLR路径处理了方法时,则模板中自动应用了新的路径。URL Router Portal Test ">Portal Link 1
">Portal Link 2
">Portal Link 3
">Portal Link 4
">Portal Link 5
使用默认URLR处理器时输出为:
而使用statics处理器时输出为:URL Router Portal Test Portal Link 1
Portal Link 2
Portal Link 3
Portal Link 4
Portal Link 5
URL Router Portal Test Portal Link 1
Portal Link 2
Portal Link 3
Portal Link 4
Portal Link 5
下面来看看如何开发URLR路径处理器吧:
创建一个名字为 cmspad_router_<文件名字>的类,实现 URLRouter接口,并实现接口里的两个函数:
class cmspad_router_myrule implements URLRouter{ public function route($pathinfo){ // 处理并输出路径所对应的内容。 } public function hyperlink($portlet = null, $method = null, $parameters = array()){ // 生成并返回该规则的URL路径。 } }将以上代码保存到 inc/urlrouters/myrule.php 文件中。然后在创建Dispatcher文件的代码中将
$dispatcher = new Dispatcher('default');改成
$dispatcher = new Dispatcher('myrule');这样,你写的规则就应用上去了。
下面给出当前默认实现(default)的源代码:
portal = $portal; } public function route($pathinfo){ while(strpos($pathinfo,'//') !== false){ $pathinfo = str_replace('//','/',$pathinfo); } $pathinfo = trim($pathinfo,' /'); if(empty($pathinfo)){ $pathinfo = $this->portal . '/' . $this->portal; } $arr = explode('/',$pathinfo); if(count($arr) > 0){ $portlet = $arr[0]; $portletObj = PortletUtil::newObject($portlet); if($portletObj === null || $portletObj === false){ $portletObj = PortletUtil::newObject($portlet = $this->portal); }else{ array_shift($arr); } } if($portletObj === null || $portletObj === false){ return false; } if(count($arr) > 0){ $portletArr = PortletUtil::newMethod($portletObj,'page' . ucfirst($arr[0])); if($portletArr === null || $portletArr === false){ $portletArr = PortletUtil::newMethod($portletObj,'page' . ucfirst($portlet)); }else{ array_shift($arr); } $portletArg = $arr; }else{ $portletArr = PortletUtil::newMethod($portletObj,'page' . ucfirst($portlet)); $portletArg = array(); } if($portletArr === null || $portletArr === false){ return false; } $contents = call_user_func($portletArr,$portletArg); if($contents){ echo $contents; } return true; } public function hyperlink($portlet = null,$method = null,$params = null){ global $_CONFIG; if(isset($_CONFIG['DISPATCH']['SCRIPT'])){ $url = $_CONFIG['DISPATCH']['SCRIPT']; }else{ $url = $_SERVER['SCRIPT_NAME']; } if(!$portlet){ $portlet = $this->portal; } if($portlet){ $url .= ($portlet == $this->portal?'':'/' . $portlet); if($method){ $url .= ($method == $portlet?'':'/' . $method); } if($params){ $url .= '/' . implode('/',$params); } } return $url; } } ?>此代码保存在 inc/urlrouters/default.php 中。