本文示例代码基于Hello Z-Blog – 插件开发创建的demoPlugin插件;有新版页面路由和旧版页面路由两种方式。
一、1.7新版路由
1.7 版本新增加了路由系统,一般来说,我们只要向系统注入一条路由规则,再实现该条路由 call 的函数,匹配成功后向该函数传入一个数组参数,就实现路由功能了。增加路由条目的关键是在配置路由规则的数组,如果对路由系统不熟悉,请在应用中心下载 Z-Blog PHP Development Kit 插件,仔细研究系统自带的路由规则。
示例:
1、搜索功能伪静态化
实现搜索功能的伪静态化:
//将注入路由的函数挂上接口 Add_Filter_Plugin('Filter_Plugin_Zbp_PreLoad', 'demoPlugin_RegRoute'); //创建搜索伪静化的规则,并挂在 Filter_Plugin_Zbp_PreLoad 接口 function demoPlugin_RegRoute() { global $zbp; $route = array ( 'posttype' => 0,//文章类型 'type' => 'rewrite',//路由的类型,可以是active,rewrite,default 'name' => 'post_article_search', //名称 'call' => 'ViewSearch', //呼叫的函数,匹配成功后call之,并传入一个含有各种匹配参数的数组 'urlrule' => '{%host%}search/{%q%}_{%page%}.html',//规则主体 'args' => //伪静类型路由的参数(出现在urlrule里的) array ( 'q' => '[^\\/_]+',//q是搜索的关键字,支持正则匹配 'page',//page是页码 ), 'only_match_page' => false,//为假表示可以匹配没有{%page%}参数的url,默认如此可以不加这一行配置 ); $zbp->RegRoute($route); } //ViewSearch函数系统已经写好了,所以只需要注入路由就可以实现搜索功能的伪静态化!
路由系统在匹配到规则后,向 call 所指定的函数 传入一个 array 数组,其格式如下:
function ViewSearch() { //获取路由系统传入参数,路由系统传入一个且只传一个含有各种匹配参数的数组 $args = func_get_arg(0); $q = $args['q']; //获取查询字符串 $page = $args['page']; //获取页面,如果有的话 //得到该匹配成功的Route路由规则 $route = $args['_route']; //可以打印出$args查看详情 var_dump($args); /* //该数组由posttype和匹配的各种参数和原始规则组成 array(4) { ["q"]=> string(7) "xxxxxxx" ["page"]=> int(1) ["posttype"]=> int(0) ["_route"]=> array(10) { //路由规则。。。 //该段省略 } } */ }
2、文章页专属下载页
- 文章页专属下载页
- 对于{%host%}post/{%id%}.html模式的访问,另外定义一条{%host%}download/{%id%}.html用于显示下载内容;
- 向ActivePlugin_demoPlugin()函数内添加如下接口挂载;
Add_Filter_Plugin('Filter_Plugin_Zbp_PreLoad', 'demoPlugin_RegRoute');
接口函数定义:
//注册一条属于文章页的下载页面,并挂在 Filter_Plugin_Zbp_PreLoad 接口 function demoPlugin_RegRoute() { global $zbp; $route = array( // 默认取 0 即 article,建议显示设置,表示当前路由无论是单页还是列表都与该类型相关; // 可按需设置 $GLOBALS['posttype'] 内的其他值,还可以自行添加类型,或者设置为 null 表示不属于任何类型; 'posttype' => 0, //0是文章 // 路由类型 (rewrite 类型使用 route 规则进行匹配,从规则中取得参数并传入 call,不匹配将跳出本规则进入下一条) 'type' => 'rewrite', // 路由名称,推荐格式:前缀_路由功能 'name' => 'plugin_demoPlugin_download', // 路由调用的函数 'call' => 'demoPlugin_ViewDownload', // 动态路由和伪静路由的原始规则 (必须) 'urlrule' => '{%host%}download/{%id%}.html', // 从伪静规则匹配到的数组中取值传给 call 的参数 (示例为 array('id', 'page') or array('cate@alias', 'page') ) 'args' => array( 0 => 'post@id', ), 'verify_permalink' => false, //1.7.1新增参数,false时不比对当前url与目标url是否相同 ); $zbp->RegRoute($route); } // 对于路由匹配到的访问,会调用这个函数 function demoPlugin_ViewDownload($arg) { // $arg就是路由系统传入的数组参数,包含匹配到的参数和其它信息; var_dump($arg); $id = $arg["post"]; //获取文章的ID //显示下载页面 //业务代码自行实现 }
3、文章页实现内容分页
对文章内容分页,使用一条规则实现;将'{%host%}post/{%id%}_{%page%}.html’改为'{%host%}post/{%id%}_{%all%}.html’,由{%all%}匹配对应位置的内容;
接口函数定义:
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,//不比对当前url与目标url是否相同 ); $zbp->RegRoute($route); return true; } function demoPlugin_ViewPost($arg) { // $arg就是路由系统传入的数组参数,包含匹配到的参数和其它信息; var_dump($arg); // 从数组获取指定下标的值 $id = $arg["post"]; //获取文章的ID $isAll = $arg["all"]; if ($isAll == 'all') { // 全文获取 // code } else { $page = $isAll; // 将文章内容分页后获取第 $page 页; // code } }
4、路由规则内实现跳转
利用路由规则实现 301,302 跳转;
//路由规则如下,请用$zbp->RegRoute()注入路由系统就可以实现了 //此路由规则type是默认规则‘default’,伪静模式或动态模式,都可以生效! $route = array( 'posttype' => 0, 'type' => 'default', 'name' => 'plugin_redierct_to_baidu', 'urlrule' => '{%host%}baidu.html', // redirect_to是http302跳转,如果需要301跳转,键名要写为redirect301_to 'redirect_to' => 'https://www.baidu.com/', ); $zbp->RegRoute($route, true);//这里需要加上第2个参数ture表示追加路由到最前 //访问https://网站/baidu.html 就会跳转到 https://www.baidu.com/ Copy to clipboardErrorCopied
5、实现网站改版301跳转
- 1.7.2 版本及以上支持
- 在网站改版之前,文章的固定链接格式为 https://网站/post/{%id%}.html
- 改版之后,文章的新 URL 格式为 https://网站/article/{%alias%}.html
//定义301重写规则并注入系统 $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 函数并实现Http 301跳转 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跳转数据 return array('StatusCode' => 301, 'Location' => $url); }
6、API实现伪静URL访问
- 1.7.2 版本及以上支持
- 默认的 API 访问为 https://网站/zb_system/api.php?mod=post&act=get&id=1
- 伪静态下可以实现 https://网站/api/post/get/?id=1
//定义API重写规则并注入系统 $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 函数 function Rewrite_API(){ global $zbp; // 标记为 API 运行模式 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']); // 载入系统和应用的 mod ApiLoadMods($GLOBALS['mods']); //进行Api白名单和黑名单的检查 ApiCheckMods($GLOBALS['mods_allow'], $GLOBALS['mods_disallow']); ApiLoadPostData(); ApiVerifyCSRF(); // 派发 API ApiDispatch($GLOBALS['mods'], $GLOBALS['mod'], $GLOBALS['act']); } Copy to clipboardErrorCopied
二、1.6及旧版
示例:
对于{%host%}post/{%id%}.html模式的访问,另外定义一条{%host%}download/{%id%}.html用于显示下载内容;向ActivePlugin_demoPlugin()函数内添加如下接口挂载;
Add_Filter_Plugin('Filter_Plugin_ViewAuto_Begin', 'demoPlugin_Rewrite');
接口函数定义:
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'] 作为参数进行查询和输出; // 也可以使用 ViewPost($m) 并配合 Filter_Plugin_ViewPost_Template 等接口; unset($m[0]); // 因为新机制的附带影响,目前需要在传值前额外处理; ViewPost($m); // 用于跳过同一接口队列中的后续操作 $GLOBALS['hooks']['Filter_Plugin_ViewAuto_Begin']['demoPlugin_Rewrite'] = PLUGIN_EXITSIGNAL_RETURN; } }