PHP实现一个简单url路由功能.docx
《PHP实现一个简单url路由功能.docx》由会员分享,可在线阅读,更多相关《PHP实现一个简单url路由功能.docx(10页珍藏版)》请在冰豆网上搜索。
PHP实现一个简单url路由功能
PHP实现一个简单url路由功能
如果一个页面的内容呈现,需要根据url上传递的参数来进行渲染。
很多时候可能是这样子写:
如果我们访问一下不存在的游戏应用,例如
后面匹配到的项,指向了某个php页面,然后根据参数获取要访问的游戏应用标识,后数据库或者缓存里查询该应用标识,如果不存在则输出错误提示,如果应用存在则加载游戏应用链接地址。
现在写一个php例子,假设我的ip为192.168.0.33,我加了一层名为router的路径,之后跟随的是“/模块名/方法名/参数1的key/参数1的value/….”
类似这样的地址:
192.168.0.33/router/Hello/router/a/b/c/d/abc/index.html?
id=3&url=http:
………………
也就是要调用Ha这个模块中的router方法,并传入url后面的参数/a/b/c/d/index………….
第一步,首先要在服务器的配置上对/router/路径进行拦截
调用某个文件夹目录下的index.php页面,假定现在所有模块使用单独的文件存放于class目录下,该目录与router平级,如下图所示:
第二步,路由分发器的实现(index.php)
1:
Doctypehtml>
2:
3:
4:
路由测试~~5:
6:
7:
8:
9:
php
10:
11:
date_default_timezone_set("Asia/Shanghai");
12:
13:
define("MODULE_DIR","../class/");
14:
15:
16:
$_DocumentPath=$_SERVER['DOCUMENT_ROOT'];
17:
$_FilePath=__FILE__;
18:
$_RequestUri=$_SERVER['REQUEST_URI'];
19:
20:
$_AppPath=str_replace($_DocumentPath,'',$_FilePath);//==>\router\index.php
21:
$_UrlPath=$_RequestUri;//==>/router/hello/router/a/b/c/d/abc/index.html?
id=3&url=http:
22:
23:
$_AppPathArr=explode(DIRECTORY_SEPARATOR,$_AppPath);
24:
25:
/**
26:
*http:
//192.168.0.33/router/hello/router/a/b/c/d/abc/index.html?
id=3&url=http:
27:
*
28:
*/hello/router/a/b/c/d/abc/index.html?
id=3&url=http:
29:
*/
30:
31:
for($i=0;$i32:
$p=$_AppPathArr[$i];
33:
if($p){
34:
$_UrlPath=preg_replace('/^\/'.$p.'\//','/',$_UrlPath,1);
35:
}
36:
}
37:
38:
$_UrlPath=preg_replace('/^\//','',$_UrlPath,1);
39:
40:
$_AppPathArr=explode("/",$_UrlPath);
41:
$_AppPathArr_Count=count($_AppPathArr);
42:
43:
$arr_url=array(
44:
'controller'=>'index',
45:
'method'=>'index',
46:
'parms'=>array()
47:
);
48:
49:
$arr_url['controller']=$_AppPathArr[0];
50:
$arr_url['method']=$_AppPathArr[1];
51:
52:
if($_AppPathArr_Count>2and$_AppPathArr_Count%2!
=0){
53:
die('参数错误');
54:
}else{
55:
for($i=2;$i<$_AppPathArr_Count;$i+=2){
56:
$arr_temp_hash=array(strtolower($_AppPathArr[$i])=>$_AppPathArr[$i+1]);
57:
$arr_url['parms']=array_merge($arr_url['parms'],$arr_temp_hash);
58:
}
59:
}
60:
61:
$module_name=$arr_url['controller'];
62:
$module_file=MODULE_DIR.$module_name.'.class.php';
63:
$method_name=$arr_url['method'];
64:
65:
if(file_exists($module_file)){
66:
include$module_file;
67:
68:
$obj_module=new$module_name();
69:
70:
if(!
method_exists($obj_module,$method_name)){
71:
die("要调用的方法不存在");
72:
}else{
73:
if(is_callable(array($obj_module,$method_name))){
74:
$obj_module->$method_name($module_name,$arr_url['parms']);
75:
76:
$obj_module->printResult();
77:
}
78:
}
79:
80:
}else{
81:
die("定义的模块不存在");
82:
}
83:
84:
85:
?
>
86:
87:
88:
获取请求的uri,然后拿到要加载的模块名、调用方法名,对uri参数进行简单的判断..
第三步,模块的编写
根据上述的uri,我们要调用的是Hello模块下的router方法,那么可以在class目录下定义一个名为Hello.class.php的文件(注意linux下是区分大小写的)
1:
php
2:
3:
classHello{
4:
5:
private$_name;
6:
private$_varValue;
7:
8:
function__construct(){
9:
10:
}
11:
12:
functionrouter(){
13:
$this->_name=func_get_arg(0);
14:
$this->_varValue=func_get_arg
(1);
15:
}
16:
17:
functionprintResult(){
18:
echo$this->_name;
19:
echo"
";
20:
echovar_dump($this->_varValue);
21:
echo"
";
22:
}
23:
}
24:
25:
?
>
同理,我们可以编写Ha模块..
这算是实现了很简单的url路由分发功能了…
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
前段时间写了个关于手机应用的api,一直是用的query_string这种地址,而且还是根据一个act参数来区分所有的动作,这种让开发人员看起来比较费眼。
本来想改写为“?
c=controller&m=method&type=3&id=1”这种形式,利用m参数来载入文件并进行实例化,后来看了sinaweiboapi是对地址进行了路由。
也决定跟风对地址路由。
本来CI框架自己自带路由效果,但是因为考虑是写api,想写的比较纯粹一点。
支持默认控制器(index)和方法(index):
viewsourceprint?
index.php
index.php/controller
index.php/controller/method
index.php/controller/method/prarme1/value1
index.php/controller/method/param1/value1/param2/value2.....
viewsourceprint?
php
define('MODULE_DIR','./classes/');
$APP_PATH=str_replace($_SERVER['DOCUMENT_ROOT'],'',__FILE__);
$SE_STRING=str_replace($APP_PATH,'',$_SERVER['REQUEST_URI']);//计算出index.php后面的字段index.php/controller/methon/id/3
$SE_STRING=trim($SE_STRING,'/');
//echo$SE_STRING.'
';
//这里需要对$SE_STRING进行过滤处理。
$ary_url=array(
'controller'=>'index',
'method'=>'index',
'pramers'=>array()
);
//var_dump($ary_url);
$ary_se=explode('/',$SE_STRING);
$se_count=count($ary_se);
//路由控制
if($se_count==1and$ary_se[0]!
=''){
$ary_url['controller']=$ary_se[0];
}elseif($se_count>1){//计算后面的参数,key-value
$ary_url['controller']=$ary_se[0];
$ary_url['method']=$ary_se[1];
if($se_count>2and$se_count%2!
=0){//没有形成key-value形式
die('参数错误');
}else{
for($i=2;$i<$se_count;$i=$i+2){
$ary_kv_hash=array(strtolower($ary_se[$i])=>$ary_se[$i+1]);
$ary_url[pramers]=array_merge($ary_url[pramers],$ary_kv_hash);
}
}
}
$module_name=$ary_url['controller'];
$module_file=MODULE_DIR.$module_name.'.class.php';
//echo$module_file;
$method_name=$ary_url['method'];
if(file_exists($module_file)){
include($module_file);
$obj_module=new$module_name();//实例化模块m
if(!
method_exists($obj_module,$method_name)){
die('方法不存在');
}else{
if(is_callable(array($obj_module,$method_name))){//该方法是否能被调用
//var_dump($ary_url[pramers]);
$get_return=$obj_module->$method_name($ary_url[pramers]);//执行a方法,并把key-value参数的数组传过去
if(!
is_null($get_return)){//返回值不为空
var_dump($get_return);
}
}else{
die('该方法不能被调用');
}
}
}
else
{
die('模块文件不存在');
}
?
>