发布于2026-07-09 阅读(0)
扫一扫,手机访问
ThinkPHP 支持中文 URL,这一点毫无疑问。但你可能会遇到 404 或者乱码——别急着怀疑框架,问题通常出在服务器对 URI 的处理环节上。直接用 /文章/详情/1 这样的路径跑在生产环境是完全可行的,关键在于 Apache 或 Nginx 是否“理解”了 UTF-8 编码后的中文。

先拿 Apache 开刀。最常见的原因不是 ThinkPHP 拒绝中文,而是 Apache 对非 ASCII 字符做了两次 decode——本来好好的 %E4%BD%A0%E5%A5%BD,被它解了一轮又一轮,最后传到 PHP 手里就成了一堆乱码。根治方法在 .htaccess 和服务器配置里:
mod_rewrite 已启用:sudo a2enmod rewrite && sudo systemctl restart apache2,这是前提。.htaccess 里务必写成 RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L],千万别写成 index.php?s=/$1——后者会丢掉原始编码,PATH_INFO 还原不出来。AllowEncodedSlashes NoDecode,直接禁止 Apache 自作主张的二次解码。public/)的 AllowOverride 是否为 All,否则 .htaccess 根本不会生效。Nginx 对中文 URI 的把控更严格,很多同学栽在 if 和 rewrite 的嵌套陷阱里。对于 TP6/TP5.1,标准做法是用 try_files:
location / 块内写入:try_files $uri $uri/ /index.php?s=$uri&$args;,这是最安全的方式。location ~ \.php$ 里再写 rewrite——Nginx 不允许嵌套 rewrite,写了就会静默失效或报错。fastcgi_param SCRIPT_FILENAME 指向真实的 index.php 路径,同时 fastcgi_split_path_info 已启用,TP 官方推荐配置里默认就带着。pathinfo_depr => '/'(默认值),那么 URI 中的中文必须是 UTF-8 编码后的百分号格式。别担心,浏览器会自动帮你编码,你完全不需要手动调用 urlencode()。我不建议在 route.php 里硬编码中文字符串作为路由名,比如 Route::get('产品介绍', 'index/product/intro')。原因有三:
Parse error。Route::get('product-intro', 'index/product/intro')->name('产品介绍');。前端生成链接时用 url('product-intro'),语义清晰,毫无编码风险。所谓“多语言伪静态”,本质是把语言标识当作一级路径,比如 /zh-CN/news/1、/en-US/news/1,而不是靠 GET 参数或子域名。这需要两层配合:
/zh-CN/ 显然不是真实目录,不能被 !-f/!-d 拦截。Route::rule(':lang/:controller/:action/:id', ':controller/:action')->pattern(['lang' => '[a-z]{2}-[A-Z]{2}']);input('lang') 获取语言标识并切换语言包,同时把 lang 绑定到 URL 生成器,确保后续 url() 自动带上当前语言前缀。UrlBuild 支持 domain 和 suffix,但不原生支持动态前缀。如果需要,得自己写个中间件或自定义 think\Url 类来注入。最后提一个最容易忽略的细节:Nginx 的 try_files 规则里 $uri 是原始请求 URI,它已经完成了 URL decode,所以中文路径到达 PHP 时是正常字符串。但在 Apache 下,如果你用了 RewriteRule + QSA,却没有设置 AllowEncodedSlashes NoDecode,那中文大概率在中途就被破坏了——这个不查日志几乎发现不了。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8