ThinkPHP 3.1/3.2 啟用 URL_ROUTER_ON 後,Page 類產生的分頁連結為原始 module/action/param/value 格式,而非路由規則定義的優美 URL (如 /article/list/cate/3/page/2),導致分頁點擊後無法匹配路由、參數遺失或 404。
U() 函式處理路由規則反向解析修改 ThinkPHP/Common/functions.php 中的 U() 函式 (約第 287 行 if(!empty($vars)) 之後) 插入以下程式碼:
/***** 路由模式下分頁連結修正開始 *****/
if (C('URL_ROUTER_ON')) {
$routeRules = C('URL_ROUTE_RULES');
if (!empty($routeRules)) {
// 組裝當前群組前綴 (若有)
$groupPrefix = defined('GROUP_NAME') ? GROUP_NAME . '/' : '';
$currentUrl = $groupPrefix . $url; // 如 Admin/Article/index/cate/3
foreach ($routeRules as $pattern => $rule) {
// $pattern: 路由規則 (如 'article/:cate/:page')
// $rule: 目標模組/動作 (如 'Article/index')
// 將規則轉為正則 (支援 :var 參數)
$regex = '@^' . str_replace('/', '\/', $pattern) . '$@';
$regex = preg_replace('@:([\w]+)@', '([^/]+)', $regex); // :cate → ([^/]+)
if (preg_match($regex, $currentUrl, $matches)) {
// 符合路由規則,重建 URL
$newUrl = $rule;
// 替換規則中的參數
$paramNames = [];
preg_match_all('@:([\w]+)@', $pattern, $paramNames);
foreach ($paramNames[1] as $i => $name) {
$newUrl = str_replace(':' . $name, $matches[$i + 1], $newUrl);
}
// 處理分頁參數 __PAGE__ (Page 類會插入)
if (strpos($newUrl, '__PAGE__') !== false) {
// 保留 __PAGE__ 讓 Page 類後續替換
} else {
// 附加剩餘參數
$usedParams = array_slice($matches, 1);
$allParams = [];
// 從原 URL 解析所有參數
preg_match_all('@/(\w+)/([^/]+)@', $url, $urlParams);
foreach ($urlParams[1] as $i => $key) {
if (!in_array($key, $paramNames[1])) {
$allParams[$key] = $urlParams[2][$i];
}
}
if ($allParams) {
$newUrl .= '/' . implode('/', array_map(function($k, $v) {
return $k . '/' . $v;
}, array_keys($allParams), array_values($allParams)));
}
}
$url = $newUrl;
break; // 只匹配第一條符合規則
}
}
}
}
/***** 路由模式下分頁連結修正結束 *****/
'URL_ROUTER_ON' => true,
'URL_ROUTE_RULES' => [
// 文章列表分頁
'article/:cate/:page' => 'Article/index', // /article/3/2 → Article/index/cate/3/page/2
'article/:cate' => 'Article/index', // /article/3 → Article/index/cate/3
// 文章詳情
'article/view/:id' => 'Article/view', // /article/view/123
// 後台管理
'admin/user/:status/:page' => 'Admin/User/index',
// 靜態頁面
'page/:name' => 'Page/view',
],
// 控制器
$page = new Page($count, 20);
$page->parameter = 'cate/3'; // 傳遞路由所需參數 (非 query string)
// 或
foreach ($_GET as $k => $v) {
if ($k !== 'p') $page->parameter .= "$k/$v/";
}
// Page 類產生連結:/article/3/__PAGE__ → U() 解析 → /article/3/2
sequenceDiagram
participant Controller
participant Page類
participant U函式
participant 路由規則
Controller->>Page類: new Page($count, 20)
Controller->>Page類: parameter = 'cate/3'
Page類->>Page類: 產生連結 '/article/3/__PAGE__'
Page類->>U函式: U('Article/index', 'cate/3/page/__PAGE__')
U函式->>路由規則: 遍歷匹配 'article/:cate/:page'
路由規則-->>U函式: 匹配成功,重建 '/article/3/2'
U函式-->>Page類: 返回修正後 URL
Page類-->>View: 輸出正確分頁連結
p,路由規則需對應 :page 或 :p。GROUP_NAME 常數需正確定義,否則前綴錯誤導致匹配失敗。Url::build(),無需此 Hack。// 建立自訂分頁類 Extend/Org/Util/PageRouter.class.php
class PageRouter extends Page {
public function show() {
$originalUrl = $this->url; // 父類生成的原始 URL
// 呼叫 U() 修正 (需確保 U() 可用)
$this->url = U($originalUrl);
return parent::show();
}
}
// 使用
import('ORG.Util.PageRouter');
$page = new PageRouter($count, 20);