根本原因是IIS将斜杠风格URL中的中文当作路径解析并按GBK解码,导致PHP收到损坏数据;须修改Page.class.php:将占位符替换改为直接替换,并用U(ACTION_NAME).'?'.http_build_query($this->parameter)强制使用标准query string格式,同时前端传参前必须用encodeURIComponent()编码。

ThinkPHP 3.2 分页中文参数在 IIS 上乱码的根本原因
不是编码设置错了,也不是数据库或页面 charset 不对——是 IIS 对 URL 路径中 / 后面的查询参数解析方式和 Apache 不同。ThinkPHP 默认用 U() 生成带斜杠风格的 URL(如 /search/index/page/2/k/北京),IIS 会把中文部分当作路径而非 query string 处理,直接按系统默认编码(通常是 GBK)解码,再传给 PHP 时就已损坏。
Page.class.php 的两处关键修改(ThinkPHP 3.2.x)
必须改 ThinkPHP/Library/Think/Page.class.php 中的 show() 方法(通常在第 82 行附近):
- 把
return str_replace(urlencode('[PAGE]'), $page, $this->url);改成return str_replace('[PAGE]', $page, $this->url);—— 避免双重编码导致 [PAGE] 占位符被误转义 - 把
$this->url = U(ACTION_NAME, $this->parameter);改成:$this->url = U(ACTION_NAME) . '?' . http_build_query($this->parameter);
—— 强制走?k=北京&page=2这种标准 query string 形式,绕过 IIS 路径解析缺陷
前端传参前必须 rawurlencode(),不能只靠 U()
即使后端改了分页类,如果搜索表单提交的是未编码的中文,$_GET 仍可能收不到完整值。尤其在 Nginx 或某些 CGI 模式下,空格、加号、斜杠会被提前截断或转义。
- 表单提交前,JS 中对每个中文参数值调用
encodeURIComponent()(等价于 PHP 的rawurlencode()) - 例如:
location.href = '/search/index?' + 'k=' + encodeURIComponent('北京朝阳') + '&page=1'; - 绝对不要依赖浏览器自动编码,也不要对整个 query string 再套一次
encodeURIComponent(),否则&和=会被破坏
为什么不用 urldecode() 在控制器里补救?
因为乱码发生在 PHP 接收到 $_GET 之前——IIS 已把“北京”转成 %C1%F1%BE%A9(GBK 编码字节),而 PHP 默认按 UTF-8 解析这些字节,结果就是 ±д。此时 urldecode() 或 iconv('gbk', 'utf-8', $_GET['k']) 都无效,因为原始 UTF-8 字节早已丢失。
立即学习“PHP免费学习笔记(深入)”;
真正可靠的路径只有一条:从源头堵住,强制所有分页链接走 ? 查询字符串,并确保每个参数值在拼接 URL 前就用 rawurlencode() 安全编码。任何试图在控制器里“修复”乱码的操作,都是在处理已经损坏的数据。



















