ThinkPHP 5 的伪静伪静态,说白了就是伪静把
index.php/Index/index这种带入口文件的 URL,变成/index/index.html或者/article/123.html这种看起来像静态页面的伪静形式。这事本身不复杂,伪静但坑不少,伪静我踩过几回,伪静记下来。伪静先搞清楚一个前提:伪静态不是伪静真静态。服务器上根本不存在那个 .html 文件,伪静全靠 rewrite 规则把请求转发给入口文件,伪静再由 TP5 的伪静路由去解析。所以浏览器地址栏看着像个静态页,伪静实际每次请求都在跑 PHP。伪静
Apache 下的伪静配置
TP5 根目录自带一个
.htaccess文件,内容大概是伪静这样:<IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine On RewriteCond %{ REQUEST_FILENAME} !-d RewriteCond %{ REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] </IfModule>这段规则的意思是:如果请求的不是真实存在的目录或文件,就统统交给 index.php 处理。看着没问题对吧?但我第一次部署的时候就翻车了——Apache 没开 rewrite 模块。查了半天代码,最后发现是
mod_rewrite没启用。Ubuntu 下执行a2enmod rewrite然后重启 Apache 就好了。这种问题很蠢,但确实耗时间。还有个细节,Apache 的
AllowOverride必须设成All,否则 .htaccess 根本不生效。很多人改了 httpd.conf 里的AllowOverride None却忘了改成 All,然后纳闷为什么规则不起作用。Nginx 下的配置
Nginx 不认 .htaccess,得直接改站点配置文件。TP5 官方文档给的规则是:
location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=$1 last; break; } }这个写法能用,但用
if判断在 Nginx 里其实不太优雅。更推荐的方式是用try_files:location / { try_files $uri $uri/ /index.php?s=$uri&$args; }两种写法效果差不多,但后者性能更好,也更符合 Nginx 的惯用法。我现在的项目基本都用 try_files 这套。
URL 重写和路由的配合
光配好 rewrite 还不够,TP5 的路由规则也得跟上。默认情况下,
/index/index/hello这种 PATH_INFO 模式的 URL 经过 rewrite 后能正常访问。但如果你想做更干净的 URL,比如/article/123.html,就得在route.php里定义路由:Route::rule('article/:id', 'index/Article/read', 'GET', [], ['id' => '\d+']); Route::rule('article/:id', 'index/Article/read', 'GET', [], ['id' => '\d+'], ['ext' => 'html']);注意那个
ext参数,加上之后才能匹配带 .html 后缀的 URL。不加的话,/article/123.html会被当成 id 是123.html,然后正则校验不过直接 404。另外 TP5 的
url_html_suffix配置项也值得关注。在config.php里设置'url_html_suffix' => 'html',配合路由规则,就能生成带 .html 的链接。用url()助手函数生成 URL 时会自动带上后缀。一个容易忽略的坑
TP5 在 Nginx 环境下,如果
pathinfo没配好,可能会出现/index.php/Index/index能访问但伪静态 404 的情况。检查fastcgi_split_path_info和fastcgi_param PATH_INFO这两项。我遇到过一台服务器,rewrite 规则完全正确,但 PATH_INFO 传不过去,最后在 Nginx 配置里补了一行fastcgi_param PATH_INFO $fastcgi_path_info;才解决。伪静态这东西,配置本身不难,难的是环境差异。Apache 和 Nginx 不一样,不同版本的 Nginx 对 try_files 的处理也有细微差别。每次换服务器环境,最好先把这一块跑通再干别的。
顶: 3353踩: 6






评论专区