我們支持3種路由模式
普通模式
_a=$app, _u=$ctl.$act
最簡單的方式,專注實現業務$act函數,不需要再寫額外代碼
為什麼參數名前面要加下劃線就不解釋了
easy模式
_easy=$app.$tpl.$ctl.$act
_easy=$app.$ctl.$act
在web開發中,通常我們在$act中輸出一個前端頁面,
easy模式下,如果未實現$act處理函數,會自動尋找並顯示對應的前端模板文件。
對於簡單的展示頁面適合使用這種路由模式
url重寫模式(需要nginx或apache配置)
apache: ^rewrite[\.\/](.*)$ /index.php?_rewrite=$1 [R,QSA]
nginx: rewrite ^/rewrite[\.\/](.*)$ /index.php?_rewrite=$1 last;
rewrite.{$app}.{$ctl}.{$act}.{$params}.html
或更加優雅的目錄式訪問方式
rewrite/{$app}/{$ctl}/{$act}/{$params}.html
其中$params為選填參數部分.格式為urlencode後的參數列表
如果想傳遞sp_uid=1&d=1.2&p=sb, 那麼$params = sp_uid%3D1%26d%3D1.2%26p%3Ds%2Fb
或sp_uid/1/d/1.2/p/sb
在某些要求url中不能帶?&特殊字符的場景下可以使用這種模式
1. 為了能通過qq oauth2登陸驗證,需要配置重寫規則
rewrite.thirdlogin.index.qqcallback.sp_uid%3D1.php
2. 資源靜態化
rewrite.upload.index.out.uidm%3D310ef4b.png
3. 支付回調
rewrite.pay.weixin.native2_notify.php
4. 微信開放平台授權回調
rewrite/web/component/message/_app_id/xxxxxxx.php
部分實現代碼
1 2 3 4 5 6 7 8 9 10 11 12 13 $a = (!empty($_REQUEST['_a']) && is_string($_REQUEST['_a'])) ? $_REQUEST['_a'] : 'web';
if (!preg_match('/^[\w\.]+$/', $a)) {
exit('invalid _app name! ' . htmlspecialchars($a));
}
$GLOBALS['_UCT']['APP'] = !empty($a) ? strtolower($a) : 'web';
$u = (!empty($_REQUEST['_u']) && is_string($_REQUEST['_u'])) ? $_REQUEST['_u'] : 'index.index';
if (!preg_match('/^[\w\.]+$/', $u)) {
exit('invalid _url name! ' . htmlspecialchars($u));
}
$u = explode('.', $u, 2);
$GLOBALS['_UCT']['CTL'] = !empty($u['0']) ? strtolower($u['0']) : 'index';
$GLOBALS['_UCT']['ACT'] = !empty($u['1']) ? strtolower($u['1']) : 'index';
easy模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 //easy 模式直接訪問模板tpl
if (!empty($_REQUEST['_easy']) && is_string($_REQUEST['_easy'])) {
$easy = explode('.', $_REQUEST['_easy']);
switch (count($easy)) {
case 4:
$_GET['_u'] = $_REQUEST['_u'] = $easy[2] . '.' . $easy[3];
if (preg_match('/^[\w\.]+$/', $easy[1])) {
$GLOBALS['_UCT']['TPL'] = $easy[1];
}
$_GET['_a'] = $_REQUEST['_a'] = $easy[0];
break;
case 3:
$_GET['_u'] = $_REQUEST['_u'] = $easy[1] . '.' . $easy[2];
$_GET['_a'] = $_REQUEST['_a'] = $easy[0];
break;
case 2:
$_GET['_u'] = $_REQUEST['_u'] = $easy[1];
$_GET['_a'] = $_REQUEST['_a'] = $easy[0];
break;
case 1:
$_GET['_a'] = $_REQUEST['_a'] = $easy[0];
break;
default:
exit('invalid _easy param! ' . htmlspecialchars($_REQUEST['_easy']));
}
}
rewrite模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 //url重寫模式
if (!empty($_REQUEST['_rewrite']) && is_string($_REQUEST['_rewrite'])) {
//1.支持apache 重寫模式下?後的參數缺失的情況
if(stripos($_SERVER['SERVER_SOFTWARE'], 'nginx') === false) {
$_REQUEST['_rewrite'] = urldecode(substr($_SERVER['QUERY_STRING'], strlen('_rewrite=')));
}
//2. 丟棄_rewrite中的後綴名
$rewrite = substr($_REQUEST['_rewrite'], 0, strrpos($_REQUEST['_rewrite'], '.'));
//3. 支持/作為分隔符
$sp = '.';
for($i = 0; $i < strlen($rewrite); $i++) {
if(in_array($rewrite[$i], array('.', '/'))) {
$sp = $rewrite[$i];
break;
}
}
$rewrite = explode($sp, $rewrite, 4);
//最後1段是必填後綴名
switch(count($rewrite)) {
case 3:
case 4: {
$_GET['_a'] = $_REQUEST['_a'] = $rewrite[0];
$_GET['_u'] = $_REQUEST['_u'] = $rewrite[1].'.'.$rewrite[2];
if(!empty($rewrite[3])) {
if(strpos($rewrite[3], '/')) {
$params = explode('/', $rewrite[3]);
for($i=0; $i+1<count($params); $i+=2) {
$_REQUEST[urldecode($params[$i])] = urldecode($params[$i+1]);
}
}
else {
foreach(explode('&', $rewrite[3]) as $p) {
list($k, $v) = explode('=', $p, 2);
$_REQUEST[urldecode($k)] = urldecode($v);
}
}
}
break;
}
case 2:
$_GET['_a'] = $_REQUEST['_a'] = $rewrite[0];
$_GET['_u'] = $_REQUEST['_u'] = $rewrite[1];
break;
case 1:
$_GET['_a'] = $_REQUEST['_a'] = $rewrite[0];
break;
default:
break;
}
}