本文示例代碼基于Hello Z-Blog – 插件開發(fā)創(chuàng)建的demoPlugin插件;有新版頁面路由和舊版頁面路由兩種方式。
一、1.7新版路由
1.7 版本新增加了路由系統(tǒng),一般來說,我們只要向系統(tǒng)注入一條路由規(guī)則,再實現(xiàn)該條路由 call 的函數(shù),匹配成功后向該函數(shù)傳入一個數(shù)組參數(shù),就實現(xiàn)路由功能了。增加路由條目的關(guān)鍵是在配置路由規(guī)則的數(shù)組,如果對路由系統(tǒng)不熟悉,請在應(yīng)用中心下載 Z-Blog PHP Development Kit 插件,仔細(xì)研究系統(tǒng)自帶的路由規(guī)則。
示例:
1、搜索功能偽靜態(tài)化
實現(xiàn)搜索功能的偽靜態(tài)化:
//將注入路由的函數(shù)掛上接口 Add_Filter_Plugin('Filter_Plugin_Zbp_PreLoad', 'demoPlugin_RegRoute'); //創(chuàng)建搜索偽靜化的規(guī)則,并掛在 Filter_Plugin_Zbp_PreLoad 接口 function demoPlugin_RegRoute() { global $zbp; $route = array ( 'posttype' => 0,//文章類型 'type' => 'rewrite',//路由的類型,可以是active,rewrite,default 'name' => 'post_article_search', //名稱 'call' => 'ViewSearch', //呼叫的函數(shù),匹配成功后call之,并傳入一個含有各種匹配參數(shù)的數(shù)組 'urlrule' => '{%host%}search/{%q%}_{%page%}.html',//規(guī)則主體 'args' => //偽靜類型路由的參數(shù)(出現(xiàn)在urlrule里的) array ( 'q' => '[^\\/_]+',//q是搜索的關(guān)鍵字,支持正則匹配 'page',//page是頁碼 ), 'only_match_page' => false,//為假表示可以匹配沒有{%page%}參數(shù)的url,默認(rèn)如此可以不加這一行配置 ); $zbp->RegRoute($route); } //ViewSearch函數(shù)系統(tǒng)已經(jīng)寫好了,所以只需要注入路由就可以實現(xiàn)搜索功能的偽靜態(tài)化!
路由系統(tǒng)在匹配到規(guī)則后,向 call 所指定的函數(shù) 傳入一個 array 數(shù)組,其格式如下:
function ViewSearch() { //獲取路由系統(tǒng)傳入?yún)?shù),路由系統(tǒng)傳入一個且只傳一個含有各種匹配參數(shù)的數(shù)組 $args = func_get_arg(0); $q = $args['q']; //獲取查詢字符串 $page = $args['page']; //獲取頁面,如果有的話 //得到該匹配成功的Route路由規(guī)則 $route = $args['_route']; //可以打印出$args查看詳情 var_dump($args); /* //該數(shù)組由posttype和匹配的各種參數(shù)和原始規(guī)則組成 array(4) { ["q"]=> string(7) "xxxxxxx" ["page"]=> int(1) ["posttype"]=> int(0) ["_route"]=> array(10) { //路由規(guī)則。。。 //該段省略 } } */ }
2、文章頁專屬下載頁
- 文章頁專屬下載頁
- 對于{%host%}post/{%id%}.html模式的訪問,另外定義一條{%host%}download/{%id%}.html用于顯示下載內(nèi)容;
- 向ActivePlugin_demoPlugin()函數(shù)內(nèi)添加如下接口掛載;
Add_Filter_Plugin('Filter_Plugin_Zbp_PreLoad', 'demoPlugin_RegRoute');
接口函數(shù)定義:
//注冊一條屬于文章頁的下載頁面,并掛在 Filter_Plugin_Zbp_PreLoad 接口 function demoPlugin_RegRoute() { global $zbp; $route = array( // 默認(rèn)取 0 即 article,建議顯示設(shè)置,表示當(dāng)前路由無論是單頁還是列表都與該類型相關(guān); // 可按需設(shè)置 $GLOBALS['posttype'] 內(nèi)的其他值,還可以自行添加類型,或者設(shè)置為 null 表示不屬于任何類型; 'posttype' => 0, //0是文章 // 路由類型 (rewrite 類型使用 route 規(guī)則進(jìn)行匹配,從規(guī)則中取得參數(shù)并傳入 call,不匹配將跳出本規(guī)則進(jìn)入下一條) 'type' => 'rewrite', // 路由名稱,推薦格式:前綴_路由功能 'name' => 'plugin_demoPlugin_download', // 路由調(diào)用的函數(shù) 'call' => 'demoPlugin_ViewDownload', // 動態(tài)路由和偽靜路由的原始規(guī)則 (必須) 'urlrule' => '{%host%}download/{%id%}.html', // 從偽靜規(guī)則匹配到的數(shù)組中取值傳給 call 的參數(shù) (示例為 array('id', 'page') or array('cate@alias', 'page') ) 'args' => array( 0 => 'post@id', ), 'verify_permalink' => false, //1.7.1新增參數(shù),false時不比對當(dāng)前url與目標(biāo)url是否相同 ); $zbp->RegRoute($route); } // 對于路由匹配到的訪問,會調(diào)用這個函數(shù) function demoPlugin_ViewDownload($arg) { // $arg就是路由系統(tǒng)傳入的數(shù)組參數(shù),包含匹配到的參數(shù)和其它信息; var_dump($arg); $id = $arg["post"]; //獲取文章的ID //顯示下載頁面 //業(yè)務(wù)代碼自行實現(xiàn) }
3、文章頁實現(xiàn)內(nèi)容分頁
對文章內(nèi)容分頁,使用一條規(guī)則實現(xiàn);將'{%host%}post/{%id%}_{%page%}.html’改為'{%host%}post/{%id%}_{%all%}.html’,由{%all%}匹配對應(yīng)位置的內(nèi)容;
接口函數(shù)定義:
function demoPlugin_RegRoute3() { global $zbp; $route = array( 'posttype' => 0, 'type' => 'rewrite', 'name' => 'plugin_demoPlugin_PostPagination', 'call' => 'demoPlugin_ViewPost', 'urlrule' => '{%host%}post/{%id%}_{%all%}.html', 'args' => array( 'post@id', 'all' => 'all|[0-9]+', ), 'verify_permalink' => false,//不比對當(dāng)前url與目標(biāo)url是否相同 ); $zbp->RegRoute($route); return true; } function demoPlugin_ViewPost($arg) { // $arg就是路由系統(tǒng)傳入的數(shù)組參數(shù),包含匹配到的參數(shù)和其它信息; var_dump($arg); // 從數(shù)組獲取指定下標(biāo)的值 $id = $arg["post"]; //獲取文章的ID $isAll = $arg["all"]; if ($isAll == 'all') { // 全文獲取 // code } else { $page = $isAll; // 將文章內(nèi)容分頁后獲取第 $page 頁; // code } }
4、路由規(guī)則內(nèi)實現(xiàn)跳轉(zhuǎn)
利用路由規(guī)則實現(xiàn) 301,302 跳轉(zhuǎn);
//路由規(guī)則如下,請用$zbp->RegRoute()注入路由系統(tǒng)就可以實現(xiàn)了 //此路由規(guī)則type是默認(rèn)規(guī)則‘default’,偽靜模式或動態(tài)模式,都可以生效! $route = array( 'posttype' => 0, 'type' => 'default', 'name' => 'plugin_redierct_to_baidu', 'urlrule' => '{%host%}baidu.html', // redirect_to是http302跳轉(zhuǎn),如果需要301跳轉(zhuǎn),鍵名要寫為redirect301_to 'redirect_to' => 'https://www.baidu.com/', ); $zbp->RegRoute($route, true);//這里需要加上第2個參數(shù)ture表示追加路由到最前 //訪問https://網(wǎng)站/baidu.html 就會跳轉(zhuǎn)到 https://www.baidu.com/ Copy to clipboardErrorCopied
5、實現(xiàn)網(wǎng)站改版301跳轉(zhuǎn)
- 1.7.2 版本及以上支持
- 在網(wǎng)站改版之前,文章的固定鏈接格式為 https://網(wǎng)站/post/{%id%}.html
- 改版之后,文章的新 URL 格式為 https://網(wǎng)站/article/{%alias%}.html
//定義301重寫規(guī)則并注入系統(tǒng) $route = array( 'posttype' => 0, 'type' => 'rewrite', 'name' => 'plugin_post_article_redierct301', 'urlrule' => '{%host%}post/{%id%}.html', 'call' => 'post_article_redierct301', 'args' => array('id'), ); $zbp->RegRoute($route); //定義Call 函數(shù)并實現(xiàn)Http 301跳轉(zhuǎn) function post_article_redierct301($arg){ global $zbp; $id = $arg["id"]; //獲取文章的ID $post = $zbp->GetPostByID($id); //拼裝新的鏈接URL $url = $zbp->host . 'article/' . rawurlencode($post->Alias) . '.html'; //返回301跳轉(zhuǎn)數(shù)據(jù) return array('StatusCode' => 301, 'Location' => $url); }
6、API實現(xiàn)偽靜URL訪問
- 1.7.2 版本及以上支持
- 默認(rèn)的 API 訪問為 https://網(wǎng)站/zb_system/api.php?mod=post&act=get&id=1
- 偽靜態(tài)下可以實現(xiàn) https://網(wǎng)站/api/post/get/?id=1
//定義API重寫規(guī)則并注入系統(tǒng) $zbp->RegRoute( array ( 'posttype' => null, 'type' => 'rewrite', 'name' => 'rewrite_api', 'call' => 'Rewrite_API', 'urlrule' => '{%host%}api/{%mod%}/{%act%}/', 'args' => array ( 'mod' => '[_a-zA-Z0-9]+', 'act' => '[_a-zA-Z0-9]+', ), ) ); //定義Call 函數(shù) function Rewrite_API(){ global $zbp; // 標(biāo)記為 API 運(yùn)行模式 defined('ZBP_IN_API') || define('ZBP_IN_API', true); ApiCheckEnable(); foreach ($GLOBALS['hooks']['Filter_Plugin_API_Begin'] as $fpname => &$fpsignal) { $fpname(); } ApiCheckAuth(false, 'api'); ApiCheckLimit(); $GLOBALS['mods'] = array(); $GLOBALS['mods_allow'] = array(); $GLOBALS['mods_disallow'] = array(); $fpargs = func_get_arg(0); $GLOBALS['mod'] = strtolower($fpargs['mod']); $GLOBALS['act'] = strtolower($fpargs['act']); // 載入系統(tǒng)和應(yīng)用的 mod ApiLoadMods($GLOBALS['mods']); //進(jìn)行Api白名單和黑名單的檢查 ApiCheckMods($GLOBALS['mods_allow'], $GLOBALS['mods_disallow']); ApiLoadPostData(); ApiVerifyCSRF(); // 派發(fā) API ApiDispatch($GLOBALS['mods'], $GLOBALS['mod'], $GLOBALS['act']); } Copy to clipboardErrorCopied
二、1.6及舊版
示例:
對于{%host%}post/{%id%}.html模式的訪問,另外定義一條{%host%}download/{%id%}.html用于顯示下載內(nèi)容;向ActivePlugin_demoPlugin()函數(shù)內(nèi)添加如下接口掛載;
Add_Filter_Plugin('Filter_Plugin_ViewAuto_Begin', 'demoPlugin_Rewrite');
接口函數(shù)定義:
function demoPlugin_Rewrite($original_url, $url) { global $zbp; $r = UrlRule::OutputUrlRegEx("{%host%}download/{%id%}.html", 'article'); // debug // ob_clean(); echo __FILE__ . "丨" . __LINE__ . ":<br>\n"; var_dump($r); // string(38) "/(?J)^download\/(?P[0-9]+)\.html$/" echo "<br><br>\n\n"; // die(); // debug $m = array(); if (preg_match($r, $url, $m) == 1) { // debug // ob_clean(); echo __FILE__ . "丨" . __LINE__ . ":<br>\n"; var_dump($m); echo "<br><br>\n\n"; // die(); // debug /** * array(3) { * [0]=> * string(16) "download/32.html" * ["id"]=> * string(2) "32" * [1]=> * string(2) "32" * } **/ // 可以使用 $m['id'] 作為參數(shù)進(jìn)行查詢和輸出; // 也可以使用 ViewPost($m) 并配合 Filter_Plugin_ViewPost_Template 等接口; unset($m[0]); // 因為新機(jī)制的附帶影響,目前需要在傳值前額外處理; ViewPost($m); // 用于跳過同一接口隊列中的后續(xù)操作 $GLOBALS['hooks']['Filter_Plugin_ViewAuto_Begin']['demoPlugin_Rewrite'] = PLUGIN_EXITSIGNAL_RETURN; } }